unk*_*656 5 .net c# cil reflection.emit marshalling
我需要[MarshalAs(UnamangedType.LPWStr)]在运行时使用System.Reflection.Emit. 这需要我创建一个继承类型MulticastDelegate(目前没有问题)、一个适当的构造函数和Invoke带有特殊编组参数的-method。
到目前为止我的 C# 代码:
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();
Run Code Online (Sandbox Code Playgroud)
我可以生成动态程序集,但是由于无效的 IL 指令,应用程序在调用“Invoke”方法时崩溃。
在使用我检测到的peverify和ildasm-tools进行仔细检查后,我上面的代码发出以下 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
)
// ...
}
Run Code Online (Sandbox Code Playgroud)
而以下应该是正确的 IL 代码:
.method public hidebysig newslot virtual instance int32 Invoke (
string marshal(lpwstr) arg0
) runtime managed
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
(即 -marshal(lpwstr)修饰符arg0!)
我如何更改上面的代码以发出正确的编组信息?
MSDN 文档没有帮助,因为它总是指过时的方法MethodBuilder.SetMarshal(UnmanagedMarshal)。此外,文档只告诉我“MarshalAs改为发出自定义属性” - 这非常无用,因为这正是我正在做的。
注意:我使用的是 .NET Core 5
为委托创建 IL 代码不是问题。我已经对其进行了测试,并且可以完美运行。我遇到的唯一麻烦是正确实施marshal(...).
这个问题已有两年多了,但我想我可能已经在这里找到了问题。
据我所知, 用来ParameterAttributes.HasFieldMarshal指示默认的封送行为将用于封送参数,它可能具有需要额外显式封送的字段struct,例如 a包含具有以下属性的字段MarshalAs:
public struct MyStruct
{
[MarshalAs(UnmanagedType.LPWStr)]
public string s; // field has explicit marshaling
}
public delegate void Foo(MyStruct s); // param uses default marshaling behavior
Run Code Online (Sandbox Code Playgroud)
当您创建ParameterBuilder(with DefineParameter) 时,您将确定默认封送行为将用于参数及其字段(相对于MarshalAs每个字段上设置的属性)。然后,对 的调用SetCustomAttribute将被忽略,因为参数的封送行为已经定义。
ParameterAttributes.None正确的行为(如您所描述的)是在定义参数时传递,您稍后将调用该参数SetCustomAttribute来设置封送行为。
(顺便说一句,我最终来到这里是因为我正在尝试同样的事情,但由于误读了文档而传递了错误的参数索引DefineParameter。)
| 归档时间: |
|
| 查看次数: |
64 次 |
| 最近记录: |