使用calli调用成员函数

时间:2013-03-03 15:06:56

标签: .net reflection cil reflection.emit

我想使用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的编组错误,可能会破坏   叠加。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

根据the documentation for calli,您使用的EmitCalli()的重载应仅用于调用非托管代码。对于托管代码,您应该调用一个带有一个参数的重载并将其设置为null(除非您使用varagrg,这是非常罕见的):

ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.HasThis, typeof<int>, [|typeof<int>|], null)