这几天有遇到要用 C#调用 C++的 dll函数的情况。C#不能直接调用 C++的dll,需要转化。
因为之前没有用过,所有网上找了很多资料,但转化的过程中,仍然踩了很多雷。
雷1:无法找到函数的入口点;
雷2:函数堆栈不对称;
下面,记录我踩雷及排雷的过程。
1,首先需要准备相关的数据转化。
常用的数据C++ 与C# 对照表:
C++ C#
int *port ref int
LPVOID Intptr
BSTR/LPCSTR/LPCTSTR string
BOOL Boolean
CHAR/WCHAR char
2,转化
C++:
__declspec(dllexport) int DBSLDD_InitSerialPort(int nPortID, LPVOID *pHandle);
转化成C#:
[DllImport("LEDDriver.dll", EntryPoint = "DBSLDD_InitSerialPort", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int DBSLDD_InitSerialPort(int nPortID, ref IntPtr pHandle);
没毛病,很完整。run 一下
没有找到,接口!!!!????
直接怀疑人生。
气冲冲的找 提供dll的人,妹的,是不是给我的dll错了,耍人咧???
结果人家信誓旦旦的说,木有问题了,还在我面前用C++完美的run了一下。
接口没有问题,为啥我的提示无法找到入口点呢, 直接懵逼。
痛苦,纠结中.............
突然想到,为啥不用反编译工具查看一下这个dll是否有这个接口。
结果找来这个工具,
木问题呀,有这个方法。
再仔细一看函数名的前后有很多 ooxx,莫非是缺少这些符号的问题,复制函数名:?DBSLDD_InitSerialPort@@YAHHPAPAX@Z 。
果然包括那些 ooxx。
改成:
[DllImport("LEDDriver.dll", EntryPoint = "?DBSLDD_InitSerialPort@@YAHHPAPAX@Z", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int DBSLDD_InitSerialPort(int nPortID, ref IntPtr pHandle);
果然,接口的问题,搞定了。
不知道为什么有那些 ooxx,可能是生成dll编译器的问题。
新的问题有来了、、、、、、
要炸了,有没有、、、、、、
继续找问题中、、、、、、、
最后查到,CallingConvention = CallingConvention.StdCall。
C# ,应该是调用放清零堆栈,改为:CallingConvention = CallingConvention.Cdecl。可能是用C++生成的dll需要这样配置。
完成的,
[DllImport("LEDDriver.dll", EntryPoint = "?DBSLDD_InitSerialPort@@YAHHPAPAX@Z", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int DBSLDD_InitSerialPort(int nPortID, ref IntPtr pHandle);
运行通过,OK了。
到此,所有的雷已经排完,心情舒畅哈。