由于公司很多底层的SDK,都是C++开发,上层的应用软件却是C# Winform程序。在实际工作的过程中,就经常碰到了C# 程序调用C++ 动态库的问题。最近一直在和C++ 打交道,C# 怎么调用C++ 类库函数。也遇到了一些问题,所以就来总结总结C#程序调用C++动态库时的各种坑。
1. 可能遇到的问题: C#在调用动态库的过程中我也遇到了以下一些问题: 1、C++中有指针,C#中需要使用指针吗? 由于C++中的动态库中有指针参数,因此我也是用.NET的不安全代码,使用了C#的指针,但是也还是出现了一些问题,如在C#中传入的参数是一个二维数组时就出现了问题,最后只能改C++函数传入参数的参数类型。 2、C#和C++中的类型如何转换呢? 虽然C#和C++比较类似,但是其给我们的参数类型我们要与C#的参数类型一一对应起来,具体看后续说明。 3、C++函数中的CallingConventionCharSet 怎么设置? 调用C++函数之前一定要先确认,否则可能出现函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配的问题。函数的CallingConvention和CharSet,可以查看动态库对应的 .h头文件。 4、如何反编译C++的dll的名称,端口? 可以通过Dependency Walker工具进行反编译查看别人写的动态库的信息 5、指针函数如何传参? 对于函数需要的指针函数,C# 调用时,可以定义委托来传入参数。 6、需要注意C++ dll 编译的平台是x86还是x64,是多字节的还是双字节的(Unicode)。
2. 通过Dependency Walke查看dll的名称,端口 下载Dependency 后将对应的C++ dll文件加载进去,就尅看到动态库的对应的信息,同时也可以通过.h 头文件查看。
3. 如何调用 c#调用c++动态库一般我们这样写 [DllImport(SDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] public static extern int IKSDK_Release(); 1. DllImport的第一个参数SDK是动态库dll的路径,此dll放在程序运行的根目录或者c:windows/sytem32下,建议在程序根目录创建一个子目录来放置相应的C++ 动态库文件,方便以后更新。
2. CallingConvention 参数是c#调用c++的方式 是个枚举 msdn解释如下:
3. CharSet参数是控制名称重整以及将字符串参数封送到函数中的方式。 默认值为 CharSet.Ansi。 4. entrypoint参数用于标识函数在 DLL 中的位置。在托管对象中,目标函数的原名或序号入口点将标识跨越交互操作边界的函数。此外,您可以将入口点映射到一个不同的名称,这实际上是将函数重命名。一般默认不设置此参数。 5. 其他参数,请查看MSDN对于 DllImportAttribute 的说明。
4. 其他说明 C# 调用C++ 动态库,还有一个特别麻烦的问题就是参数对于的问题。后续会结合网上的资料总结一份详细的对照表。
|
|