我花了一整天的时间来解决这个问题,我不希望任何其他人也必须这样做。所以这是问题和解决方案:
问题:当您尝试在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));
}
当你运行它时,它抱怨你已经使堆栈失去平衡(在noes!)并且你真的不应该继续。它还说你应该检查方法的签名,以确保它们匹配。
谎言所有的谎言。
修复:您需要做的是在DLLImport语句中添加一个小小的东西:
这是修复
[DllImport("testdll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int Addints(int a, int b);
是的,那CallingConvention的事情? Reeeeeeeeeeealy很重要。
其他一些提示:
- 确保为同一目标构建dll和C#exe。分别为Win32和x86(例如)
- 确保您的dll是使用/ clr选项构建的(项目属性 - 配置属性 - 常规)
- 请记住,您的C ++ int,float,string可能与边界另一侧的大小不同(选中here以查看类型如何匹配)
- 并为一个非常好的一步一步的例子检查programmersnotebook.wordpress.com/2010/01/18/calling-a-cpp-dll-from-cs
答案 0 :(得分:1)
shedemon
我讨厌这样做,但你的答案不是完整的答案。默认情况下,C / C ++使用Cdecl调用约定,因此您必须将其转换为明显的原因。
真正的解决方案只是在C ++代码中声明调用约定。
http://msdn.microsoft.com/en-us/library/zxk0tw93(v=VS.100).aspx
还有其他调用约定http://msdn.microsoft.com/en-us/library/984x0h58.aspx所以你的答案实际上取决于C / C ++非托管代码的调用约定。
我怀疑VS2008与.NET Framework 3.5有什么关系呢。
只需将您的功能更改为:
__declspec(dllexport) int __stdcall Addints(int a, int b);
答案 1 :(得分:0)
简短版本:
确保C#中的DllImport语句包含CallingConvention参数设置为CallingConvention.Cdecl
见上文了解更多详情
答案 2 :(得分:0)
是的,这很可爱。然而它也有效 - 阅读我写得更紧密的内容我说这是对“你在例子中给出的典型声明”的修正。您可能会问什么样的例子?那么这里有几个:
dotnetperls.com/dllimport
programmersnotebook.wordpress.com/2010/01/18/calling-a-cpp-dll-from-cs/
blogs.msdn.com/b/jonathanswift/archive/2006/10/02/780637.aspx
msdn.microsoft.com/en-us/library/aa984739(VS.71).aspx
msdn.microsoft.com/en-us/library/26thfadc.aspx
www.codeguru.com/columns/kate/article.php/c3947
www.apachetechnology.net/KC/NativeDLL2Net.aspx
到目前为止,我还没有看到那种变体。然而,如果他们两个工作,那么摩擦是什么?如果你需要荣誉,那么你去吧:勇敢!荣誉!现在人们有两种选择可供选择。哦,顺便说一下你的“答案不是完整答案”:
(C++ .h) extern "C" {
__declspec(dllexport) int __stdcall Addints(int a, int b); }
(C++ .cpp) int __stdcall Addints(int a, int b) {
return a+b; }
您还需要更改cpp文件。
再次 - 我在VS2010上使用.Net 4(不确定你在那里引用了关于VS2008的评论。)
答案 3 :(得分:0)
很抱歉,之前发生的断开链接可以在此处找到平台调用数据类型: