二月 22, 2013

C#调用C/C++动态库必须注意的几个问题

Written by

经常需要封装一些C/C++函数放入动态库中给C#程序调用,通常情况下直接写成如下形式即可:

C#封装调用:

[DllImport("depressor.dll")]
private static extern void DataDepress(ushort[] data);

但是经常出现找不到函数、出现PInvoke错误、传入的数据是一堆莫名其妙的数值之类的错误。

实际上,DLLImport的几个参数非常非常重要,这些值的设置直接影响到了是否能够找到函数、函数调用时的压栈方式、参数传入的是否正确有直接的关系。

以下几个问题必须注意:

1、dll中的函数前必须加入extern “C”,否则会按照C++方式编译,函数会是ZxA+函数名之类的函数名称,导致找不到函数的错误;

2、在C#中做函数封装时,函数必须加入CallingConvention = CallingConvention.Cdecl标签,按照C格式调用,否则会报PInvoke错误;

3、在C#中做函数封装时,函数必须加入CharSet = CharSet.Ansi标签,保证参数以Ansi方式传入,否则传入地址混乱!!!

举例:

C++ Dll函数:

 extern "C" DEPRESSOR_API void DataDepress(ushort* cprs);

C#封装调用:

[DllImport("depressor.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern void DataDepress(ushort[] data);

4、未处理DllNotFoundException:无法加载 DLL“EKFLib.dll”: 内存位置访问无效。 (异常来自 HRESULT:0x800703E6)

这通常是因为dll中直接给空指针赋值等C++ dll中的bug导致的问题。

因为我刚刚解决了一个bug:
C++dll中的一个对象构造函数时调用了一个回调函数,此时回调函数还是个未赋值的指针,所以出现内存位置访问无效的错误,但C#中提示的是:

未处理DllNotFoundException
无法加载 DLL“EKFLib.dll”: 内存位置访问无效。 (异常来自 HRESULT:0x800703E6)。

不要被DllNotFoundException误导了。

Category : .NetC/C++C#

Tags :

Comments

One Response

  1. Hendrix说道:

    I don’t even know what to say, this made things so much easeir!

发表评论

电子邮件地址不会被公开。

Proudly powered by WordPress and Sweet Tech Theme