【发布时间】:2012-10-21 01:21:08
【问题描述】:
我有一个供应商的 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。不管我怎么尝试,都没有效果。
我在阅读 StackOverflow 上的一篇文章后向供应商提到,返回字符串是危险的,永远不应该这样做。他们的回答是:
"该页面上提到的字符串返回问题不适用于 我们的职能。它们返回一个指向静态分配字符串的指针,因此您不需要释放它(也不能尝试这样做)。看起来“UnmanagedType.LPStr”应该可以工作(尽管 IntPtr 也应该可以工作,只要进行适当的转换或转换)。
更新 #1:正如评论中提到的,在这篇文章之前,我使用的是 uint,而不是 ulong。我只是认为我让比较看起来更好。 uint 和 ulong 都不起作用。
更新 #2:也许给出实际的函数名称会有所帮助。它是犰狳 CreateCodeShort3A。展望未来,我使用的是纯 .NET,但我仍然需要与之交互,只是目前还不太可能。不仅如此,这个问题让我很好奇为什么我不能解决像 P/Invoke 这样看似简单的事情。毕竟,有多少种变化? (不是一个严肃的问题)。
【问题讨论】:
-
这可能不是主要问题,但 C++ 中的“unsigned long”通常等同于 C# 中的“uint”,而不是“ulong”。 (类似地,C++ 中的“long”通常是 C# 中的“int”)。另一方面,“unsigned long long”相当于 C# 中的“ulong”。
-
在这篇文章之前,我使用的是 uint,而不是 ulong,只是为了写这个问题,我把它改成了 ulong,这也失败了。我尝试了无数次,或者至少,相当多的排列,到目前为止没有任何效果。
-
您忘记了调用约定 - 您需要将
CallingConvention = CallingConvention.Cdecl作为 DllImport 的一部分,否则它使用 StdCall 调用约定,这是不正确的并导致此错误
标签: c# dll pinvoke dllimport interopservices