【发布时间】:2011-01-14 16:29:12
【问题描述】:
我已经用了一天的时间来解决这个问题,我不希望其他人也这样做。所以这是问题和解决方案:
问题:在 C# 代码中尝试使用 C++ dll 中的方法时,您会遇到 PInvokeStackImbalance 异常。这是您在示例中看到的典型声明...
不起作用的示例
(C++ .h file)
extern "C" {
__declspec(dllexport) int Addints(int a, int b);
}
(C++ .cpp file)
extern int Addints(int a, int b) {
return a+b;
}
(C# .cs file)
[DllImport("testdll.dll")]
static extern int Addints(int a, int b);
static void Main(string[] args)
{
Console.WriteLine("Hello world lets add some stuff");
Int32 a = 3;
Int32 b = 5;
Console.WriteLine(Addints(a,b));
}
当您运行它时,它会抱怨您的堆栈不平衡(不正确!)并且您真的不应该继续。它还说您应该检查方法的签名以确保它们匹配。
谎言都是谎言。
修复:您需要做的是在您的 DLLImport 语句中添加一个 ~tiny 的东西,如下所示:
这是解决办法
[DllImport("testdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int Addints(int a, int b);
是的,那是 CallingConvention 的事吗?很重要。
其他一些提示:
- 确保为同一个目标构建 dll 和 C# exe。 Win32和x86(例如)分别
- 确保您的 dll 是使用 /clr 选项构建的(项目属性 - 配置属性 - 常规)
- 请记住,您的 C++ int、float、string 在边界另一侧的大小可能不同(检查 here 以查看类型如何匹配)
- 对于一个非常好的逐步示例,请查看programmersnotebook.wordpress.com/2010/01/18/calling-a-cpp-dll-from-cs
【问题讨论】:
-
您应该能够在 Windows 上使用默认调用约定,如果您不能,那么您可能会遇到其他问题。我当然可以在不声明调用约定的情况下导入非托管库。
-
您应该做的是提出这个问题,然后在下面提供您的“修复”部分作为答案。这是一个问答网站,不是论坛。见stackoverflow.com/about
-
我应该添加我使用的库,必须准确定义 8、16、32 和 64 位有符号和无符号数字。 .NET 恰好定义了相同的类型。
-
Hello First-Post trolls... Ramhound,我的配置是 VS2010,XP 上的 .NET4。我的设置没有问题。 SwDevMan81,哎呀,如果你等一下而不是跳到我身上,你会看到我那样做的:P 和拉米?是的,我尝试了所有这些,但你仍然没有得到我帖子的要点。只是想帮助人们,如果您不欣赏,请见谅。
-
我有完全相同的设置,我的非托管库可以通过声明调用约定来导入,你的解决方案不是完整的答案。
标签: c# windows dll pinvoke dllimport