I need to create a dynamic .NET delegate with specially marshalled parameters (e.g. [MarshalAs(UnamangedType.LPWStr)]
) at runtime using System.Reflection.Emit
. This requires me to create a type inheriting MulticastDelegate
(no problems so far), an appropriate constructor, and the Invoke
-method with the specially marshalled parameters.
My C# code so far:
TypeBuilder type_builder = ...;
MethodBuilder method_builder = type_builder.DefineMethod(
"Invoke",
MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Public,
CallingConventions.Standard,
typeof(int),
new[] { typeof(string) } // only an example - this array could hold any number of parameter types
);
ParameterBuilder parameter_1 = invoke.DefineParameter(1, ParameterAttributes.HasFieldMarshal, "arg0");
parameter_1.SetCustomAttribute(new CustomAttributeBuilder(
typeof(MarshalAsAttribute).GetConstructor(new[] { typeof(UnmanagedType) }),
new object[] { UnmanagedType.LPWStr }
));
// ...
type_builder.CreateType();
I can generate the dynamic assembly, however the application crashes upon invocation of the 'Invoke'-method due to invalid IL instructions.
After a closer inspection using the peverify
and ildasm
-tools I detect, that my code above emits the following IL:
.method public hidebysig newslot virtual instance int32 Invoke (
string arg0
) runtime managed
{
.param [1]
.custom instance void [System.Private.CoreLib]System.Runtime.InteropServices.MarshalAsAttribute::.ctor(
class [System.Private.CoreLib]System.Runtime.InteropServices.UnmanagedType) = (
01 00 15 00 00 00 05 00 53 08 0c 41 72 72 61 79 /* ...huge binary blob... */ 00 00 00 00
)
// ...
}
Whereas the following should be the correct IL code:
.method public hidebysig newslot virtual instance int32 Invoke (
string marshal(lpwstr) arg0
) runtime managed
{
// ...
}
(Namely the marshal(lpwstr)
-modifier on arg0
!)
My Question
How do I have to change the code above to emit the correct marshalling information?
The MSDN documentation is not helping, as it always refers to the obsolete method MethodBuilder.SetMarshal(UnmanagedMarshal)
. Furthermore, the documentation only tells me to "emit the MarshalAs
custom attribute instead" - which is pretty unhelpful, because this is exactly what I am doing.
Note: I am using .NET Core 5
EDIT:
Creating the IL code for a delegate is not a problem. I've tested it and it works flawlessly. The only trouble I have is correctly implementing marshal(...)
.