簡體   English   中英

與C#中的C / C ++例程接口會導致裂痕

[英]Interfacing with C/C++ routine in C# causes rip

我有一個供應商的API調用,我想在我的C# Windows Forms應用程序中使用它。 問題是,無論我嘗試什么P / Invoke ,我都會在線路上崩潰,說明調用已使堆棧不平衡。 我曾嘗試與供應商合作,但是他們沒有Visual Studio 2012,也沒有C#或.NET的經驗,經過幾封來回電子郵件,他們基本上解決了問題。

這是他們的官方C / C ++聲明

const char *<dll name here>(int Param1,
                            const char *Param2,
                            const char *Param3,
                            unsigned long Param4,
                            unsigned short Param5,
                            unsigned short Param6,
                            unsigned short Param7,
                            unsigned short Param8,
                            unsigned short Param9);

這是我最近嘗試的P / Invoke DLLImport行。

[System.Runtime.InteropServices.DllImport(
    "<dll name here>", EntryPoint = "<AnsiFunctionName>", ExactSpelling = true,
    CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
public static extern String <AnsiFunctionName>(int Param1,
                                               String Param2,
                                               String Param3,
                                               ulong Param4,
                                               Int16 Param5,
                                               Int16 Param6,
                                               Int16 Param7,
                                               Int16 Param8,
                                               Int16 Param9);

這是實際的錯誤消息:

主題行:檢測到PInvokeStackImbalance

對P / Invoke函數''的調用已使堆棧不平衡。 這可能是因為托管PInvoke簽名與非托管目標簽名不匹配。 檢查P / Invoke簽名的調用約定和參數是否與目標非托管簽名匹配。

我嘗試了各種方法,甚至設置了void返回類型。 我嘗試不使用返回類型。 我嘗試代替Strings,StringBuilders和IntPtrs。 無論我嘗試了什么,都無濟於事。

我在閱讀了Stack Overflow上的一篇文章后向供應商提到,返回字符串是危險的,絕不應該這樣做。 他們的回應是:

“該頁面上提到的字符串返回問題不適用於我們的函數。它們返回指向靜態分配的字符串的指針,因此您無需釋放它(也不必嘗試這樣做)。它看起來像“ UnmanagedType.LPStr”應該可以工作(盡管通過適當的轉換或強制轉換,IntPtr也可以工作)。

更新#1:如評論中所述,在撰寫本文之前,我一直使用uint而不是ulong。 我只是認為我使比較看起來更好。 uint和ulong都不起作用。

更新#2:也許提供實際的函數名稱會有所幫助。 它是犰狳CreateCodeShort3A。 展望未來,我使用的是純.NET,但我仍然需要與之交互,只是目前尚無法實現。 不僅如此,這個問題讓我感到好奇,為什么我無法解決看似簡單的P / Invoke問題。 畢竟,有多少種變化? (不是一個嚴重的問題)。

這是我可以看到的可能性:

  1. 返回值不應為String 使用IntPtr並使用Marshal.PtrToStringAnsi轉換為字符串。
  2. C ++類型的unsigned long應該與uint匹配。 您在64位類型的C#中使用了ulong 在Windows上的C ++中, unsigned long是32位無符號類型。
  3. C ++類型的unsigned short應該與ushort相匹配。
  4. C ++ DLL使用的調用約定可能是cdecl CallingConvention = CallingConvention.Cdecl添加到您的P / Invoke中
  5. 不要將SetLastError用於此類功能。 與Win32 API函數一起使用,該函數通過GetLastError返回錯誤條件。 該DLL文件幾乎肯定沒有。

因此,P / Invoke應該看起來像這樣:

[DllImport(@"mydll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern IntPtr FunctionName(
    int Param1, 
    string Param2, 
    string Param3, 
    uint Param4, 
    ushort Param5, 
    ushort Param6, 
    ushort Param7, 
    ushort Param8, 
    ushort Param9
);

暫無
暫無

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

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