天天看点

c#调用c++动态库的一些理解

c#调用c++动态库一般我们这样写

  CallingConvention 参数是c#调用c++的方式 是个枚举 msdn解释如下

  

Cdecl

调用方清理堆栈。这使您能够调用具有 varargs 的函数(如 Printf),使之可用于接受可变数目的参数的方法。 

FastCall

不支持此调用约定。

StdCall

被调用方清理堆栈。这是使用平台 invoke 调用非托管函数的默认约定。 

ThisCall

第一个参数是 this 指针,它存储在寄存器 ECX 中。其他参数被推送到堆栈上。此调用约定用于对从非托管 DLL 导出的类调用方法。 

Winapi

 从上面来看Winapi方式是根据系统自动选择调用规约的。 而thisCall是对c++类的调用方法。 所以 一般情况下我们选择Winapi就可以了。

c#调用dll另一个难点:数据类型转换

<a href="http://wenku.baidu.com/link?url=SihlxtHC-HMcEhq3izpd2bux8rNaKOMTpu8NPqjdYlLSwYSV1CqNJdVbxkaZm7OqaaSTEK-KUJqX5jbtkdpnUZ_38No4tsrgqCsf7Th5dqK" target="_blank">http://wenku.baidu.com/link?url=SihlxtHC-HMcEhq3izpd2bux8rNaKOMTpu8NPqjdYlLSwYSV1CqNJdVbxkaZm7OqaaSTEK-KUJqX5jbtkdpnUZ_38No4tsrgqCsf7Th5dqK</a>

百度文库这篇文章基本把c++与c#的对应数据类型总结完了。但是为什么这里还要说呢

1,百度文库这篇文章,包括大部分度娘的类型转换的资料中 对c++中的返回值类型char[] 都转换成了char[] 没做任何改变。

  c++中char占一个字节,assic编码。而c#中的char占2个字节(我是在中文版的vs中测试的)。

  如果这样转换就会出现问题,很容易发生越界,或者读写到受保护的内存等问题。

  解决方法是 把char[] 变成c#中的byte[] ,再用Encoding.Assic.getstring方法转换。

2,关于指针,c++所有的指针 在c#上用Intptr ,问题又来了。假如返回的Intptr是个数组指针,在c#中我们怎么读取数组里面的元素呢?

  Marshal.Copy();  

Marshal类是c#中专门把非托管内存转换成托管内存的神器,不需要unsafe。 Marshal中copy方法是最最常用的方法。里面有16个重载。能解决目前你能遇到的大部分问题。

msdn中对各个重载解释如下

名称

说明

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146625(v=vs.95)">Copy(Byte[], Int32, IntPtr, Int32)</a>

安全关键。将一维的托管 8 位无符号整数数组中的数据复制到非托管内存指针。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146626(v=vs.95)">Copy(Char[], Int32, IntPtr, Int32)</a>

安全关键。将数据从一维的托管字符数组复制到非托管内存指针。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146627(v=vs.95)">Copy(Double[], Int32, IntPtr, Int32)</a>

安全关键。将数据从一维的托管双精度浮点数组复制到非托管内存指针。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146628(v=vs.95)">Copy(Int16[], Int32, IntPtr, Int32)</a>

安全关键。将一维的托管 16 位有符号整数数组中的数据复制到非托管内存指针。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146629(v=vs.95)">Copy(Int32[], Int32, IntPtr, Int32)</a>

安全关键。将数据从一维的托管 32 位有符号整数数组复制到非托管内存指针。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146630(v=vs.95)">Copy(Int64[], Int32, IntPtr, Int32)</a>

安全关键。将一维的托管 64 位有符号整数数组中的数据复制到非托管内存指针。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146631(v=vs.95)">Copy(IntPtr, Byte[], Int32, Int32)</a>

安全关键。将数据从非托管内存指针复制到托管 8 位无符号整数数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146632(v=vs.95)">Copy(IntPtr, Char[], Int32, Int32)</a>

安全关键。将数据从非托管内存指针复制到托管字符数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146633(v=vs.95)">Copy(IntPtr, Double[], Int32, Int32)</a>

安全关键。将数据从非托管内存指针复制到托管双精度浮点数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146634(v=vs.95)">Copy(IntPtr, Int16[], Int32, Int32)</a>

安全关键。将非托管内存指针中的数据复制到托管 16 位有符号整数数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146635(v=vs.95)">Copy(IntPtr, Int32[], Int32, Int32)</a>

安全关键。将非托管内存指针中的数据复制到托管 32 位有符号整数数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ms146636(v=vs.95)">Copy(IntPtr, Int64[], Int32, Int32)</a>

安全关键。将非托管内存指针中的数据复制到托管 64 位有符号整数数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/a53bd6cz(v=vs.95)">Copy(IntPtr, Single[], Int32, Int32)</a>

安全关键。将数据从非托管内存指针复制到托管单精度浮点数组。

c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解
c#调用c++动态库的一些理解

<a href="http://technet.microsoft.com/zh-cn/library/ez2e4559(v=vs.95)">Copy(Single[], Int32, IntPtr, Int32)</a>

安全关键。将数据从一维的托管单精度浮点数组复制到非托管内存指针。

<a href="http://technet.microsoft.com/zh-cn/library/system.runtime.interopservices.marshal.copy(v=vs.95)#mainBody"> </a>

我们也可以使用共享内存的方式进行操作。部分代码如下

<a href="http://files.cnblogs.com/Bonker/Win32Interop.zip" target="_blank">这里是共享内存的辅助类  主要是一些api函数</a>

其实Intptr本质也是一个Int,Int在c#中和Int32是一样的。所以基本上指针,Long,int在c#中都是int。只是这样些 方便大家知道他是c++中的什么类型,方便转换而已。

3,c++中的函数指针  与c#中的委托

这是c++中对函数指针的定义

对应c#中的例子如下

4,我们知道int是占4个字节的。 

  下面这个是c++的一个方法

假如我们把此函数翻译成c#中的下面这个函数

我们在c#调用此方法

uint16 m_HiWi_temp = (uint)BCamera.CAMER_GetPropery(m_hCamer, CMRCTL.OUT_SIZE);

发现一个很有趣的问题,此处调用没有问题。也有值,但是他是取的int32中4个字节的2个字节。

我们看原本c++对此函数的调用

本来CAMER_GetPropery函数只返回了一个long类型。c++中通过指针的转换。把long类型转换成了 pulong,也是ulong的数组。

那c#中怎么我们该怎么调用呢

这里举这个例子是说c++有时真的就是返回一个int类型,但是在c++中可以轻松把int类型通过指针轻松转换成两个uint16的数组。所以c#中我们再转换的时候一定有注意了。

总结:其实数据类型的转换主要是对数据存储空间的转换,c++中的数据类型占用多大的空间,只要转换成c#中占同等空间的数据类型就可以了。只是c#看哪种数据类型在操作相应的操作方便些。

QQ:519841366

本页版权归作者和博客园所有,欢迎转载,但未经作者同意必须保留此段声明,

且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利