2013-03-03 84 views
2

我想使用calli調用.NET對象的成員函數。我可以調用靜態函數接受一個int並返回一個int就好使用下面的代碼:使用calli調用成員函數

// 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編程」建議它應該可以工作,但我可能讀錯了。 Reflector也認爲某些事情不太正確,並聲稱這個電話被混淆了。它的最好的猜測是「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

根據the documentation for calli,您使用的EmitCalli()的超負荷應該只用於調用非託管代碼。對於託管代碼,你應該調用重載需要一個參數,並將其設置爲null(除非你使用varagrg,這是極爲罕見的):

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

非常感謝。實際上,第二個參數在該重載中有不同的類型,但是這是有效的:EmitCalli(OpCodes.Calli,System.Reflection.CallingConventions.HasThis,type of ,[| typeof |],null) – user2129056 2013-03-03 22:52:10

+0

@ user2129056正確,固定。 – svick 2013-03-03 23:07:19