我想使用calli
调用.NET对象的成员函数。我可以调用一个带有int的静态函数,并使用以下代码返回一个int:
// push the int argument
// push the address obtained using Ldftn
ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, typeof<int>, [|typeof<int>|])
// correct result now on stack
我希望我可以使用类似下面的内容来调用也接受int并返回int的成员函数。杰森博克的“CIL编程”建议它应该有效,尽管我可能读错了。反射器也认为某些事情不太正确,并声称呼叫是混淆的。它的最佳猜测是“return (int) *ptr1(num1);
”,这与静态调用的内容相同:
ilg.Emit (OpCodes.Ldarg_0)
// push the int argument
// push the address
ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, typeof<int>, [|typeof<int>|])
当我调用第二个片段时,我收到以下消息。不用说,我没有使用编组或类似的东西。
运行时遇到了致命错误。错误的地址 在0xed470d3f处,在线程0x20e50上。错误代码是0xc0000005。 此错误可能是CLR中的错误,也可能是不安全或不可验证的错误 用户代码的一部分。此错误的常见来源包括用户 COM-interop或PInvoke的编组错误,可能会破坏 叠加。
我做错了什么?
答案 0 :(得分:1)
根据the documentation for calli
,您使用的EmitCalli()
的重载应仅用于调用非托管代码。对于托管代码,您应该调用一个带有一个参数的重载并将其设置为null
(除非您使用varagrg
,这是非常罕见的):
ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.HasThis, typeof<int>, [|typeof<int>|], null)