c# 调用c++非托管DLL调试报错
报错信息:Invoke调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配
关于C#调用系统API 提示PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。这类问题解决方案。
首先按照网上教程尝试了很多方法:
1
改C#中的声明,在DllImport("")中添加 CallingConvention=CallingConvention.Cdecl
[DllImport("Kernel32.dll")] 改成
[DllImport("Kernel32.dll",CallingConvention = CallingConvention.Cdecl)]
2
DLL的导出函数前声明__stdcall。
C++ 代码加入__stdcall 把,“允许不安全代码”,“启用非托管代码调试“去掉这样才行
C++的"_declspec"和C#的“CallingConvention=CallingConvention.Cdecl”
直接调用可以解决,采用委托形式不行
[DllImport(“*.dll")]
static extern int Test_STDCALL(int i);
3
把方法参数中long改成int
例
[DllImport("ht32dll.dll")]
public static extern long Usb_DelHtFile(string filename,long mIndex);
改成:
[DllImport("ht32dll.dll")]
public static extern int Usb_DelHtFile(string filename, int mIndex);
WinAPI的long类型是32位的,而C#的long是64位的,这就导致堆栈不对称。将最后一个”long lParam” 改为 “int wParam”, 因为C#中int是32位的. 并且将之后有涉及到SendMessage函数的参数适当地转成int型
4
http://www.pinvoke.net/default.aspx/ 这里面提供C#和VB调用所有API的方法和说明
例如,你的方法是user32.dll中的SetWindowLong()方法,就从左面目录树中查找User32 ,点开目录后再去找SetWindowLong,右边就会显示关于C# 和VB调用SetWindowLong的参数设置和相关说明。
5
可以通过VS的异常窗口,取消掉对 PInvokeStackImbalance异常的检测:
点击VS的“调试 - 异常”,打开异常窗口,展开选择“Managed Debugging Assistants\PInvokeStackImbalance”,去掉对应的“引发”可选框。
(最后采用该方法暂时解决,但总感觉还有深层隐匿问题,如有小伙伴有更好的方法,请评论告知,多谢)
具体请移步参考
__stdcall 和_cdecl 的区别
https://blog.csdn.net/dengziliang001/article/details/17448789
C#调用C++的DLL搜集整理的所有数据类型转换方式
https://blog.csdn.net/wjeson/article/details/8263335
关于调用系统API 提示PInvoke 签名与非托管的目标签名不匹配问题的解决方案https://blog.csdn.net/zhaoyun927/article/details/52210371
托管调试助手 "PInvokeStackImbalance":的调用导致堆栈不对称。
https://blog.csdn.net/jinhuicao/article/details/83584973