C#调用非托管DLL--[2]PInvoke 签名与非托管的目标签名不匹配

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”,去掉对应的“引发”可选框。

(最后采用该方法暂时解决,但总感觉还有深层隐匿问题,如有小伙伴有更好的方法,请评论告知,多谢)

C#调用非托管DLL--[2]PInvoke 签名与非托管的目标签名不匹配_第1张图片

C#调用非托管DLL--[2]PInvoke 签名与非托管的目标签名不匹配_第2张图片

 

 

具体请移步参考

__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

 

你可能感兴趣的:(c#基础)