簡體   English   中英

調用PInvoke函數'[…]'已使堆棧不平衡

[英]A call to PInvoke function '[…]' has unbalanced the stack

我在已經使用了一段時間的某些東西上遇到了這個奇怪的錯誤。 這可能是Visual Studio 2010中的新事物,但我不確定。
我試圖從C#調用用C ++編寫的無用函數。
從我在互聯網上閱讀的內容和錯誤消息本身來看,這與C#文件中的簽名與C ++中的簽名不同,但我確實看不到它有關。
首先,這是我下面不需要的功能:

TEngine GCreateEngine(int width,int height,int depth,int deviceType);

這是我在C#中的函數:

[DllImport("Engine.dll", EntryPoint = "GCreateEngine", CallingConvention = CallingConvention.StdCall)]  
        public static extern IntPtr CreateEngine(int width,int height,int depth,int device);

當我調試C ++時,我看到所有參數都很好,因此我只能認為這與從TEngine(這是一個指向CEngine的類的指針)到IntPtr的轉換有關。 我以前在VS2008中使用過它,沒有問題。

我有一個_cdecl c ++ dll,我從Visual Studio 2008毫無問題地調用了它,然后Visual Studio 2010中的相同代碼無法正常工作。 我得到了相同的PInvoke ...以及不平衡堆棧錯誤。

對我來說,解決方案是在DllImport(...)屬性中指定調用約定:From:

[DllImport(CudaLibDir)] 

至:

[DllImport(CudaLibDir, CallingConvention = CallingConvention.Cdecl)]

我猜他們改變了.NET 3.5和.NET 4.0之間DLLImport的默認調用約定嗎?

也可能是在.NET Framework 3.5版中,默認情況下禁用了pInvokeStackImbalance MDA。 在4.0(或VS2010)以下,默認情況下啟用

是。 從技術上講,代碼始終是錯誤的,並且以前版本的框架都對其進行了無提示的更正。

引用.NET Framework 4遷移問題文檔 :“為了提高與非托管代碼的互操作性,現在平台調用中的錯誤調用約定會導致應用程序失敗。在以前的版本中,封送處理層將這些錯誤解決了。如果二進制文件無法更新,則可以在應用程序的配置文件中包含< NetFx40_PInvokeStackResilience >元素,以使調用錯誤能夠像早期版本一樣在堆棧中得以解決。但是,這可能會影響應用程序的性能。”

解決此問題的一種簡單方法是指定調用約定,並確保它與DLL中的相同。 __declspec(dllexport)應該產生cdecl格式。

[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]

也許問題出在調用約定上。 您確定非托管函數已編譯為stdcall,而不是其他(我想是fastcall)嗎?

如果您的DLL的名稱為MyDLL.dll,並且您要在Dll中使用函數MyFunction ,請使用以下代碼

[DllImport("MyDLL.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void MyFunction();

這對我有用。

以我的情況(使用Intel Fortran 2011 XE編譯的VB 2010和DLL),當我的應用程序針對.NET Framework 4時存在問題。如果我將目標框架更改為3.5版,則一切正常。 因此,我想原因是.Net Framework 4中引入了某些原因,但目前我不知道哪個

更新:通過重新編譯Fortran DLL並顯式指定STDCALL作為DLL中導出名稱的調用約定來解決了該問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM