C#调用c++Dll结构体数组指针的问题
- 格式:pdf
- 大小:111.50 KB
- 文档页数:4
C#调用c++Dll结构体数组指针的问题
C#调用c++dll文件是一件很麻烦的事情,首先面临的是数据类型转换的
问题,网上有一大堆得转换对应表,也有一大堆的转换实例,但是都没有强调一
个更重要的问题,就是c#数据类型和c++数据类型占内存长度的对应关系。
如果dll文件中只包含一些基础类型,那这个问题可能可以被忽略,但
是如果是组合类型(这个叫法也许不妥),如结构体、类类型等,在其中的成员
变量的长度的申明正确与否将决定你对dll文件调用的成败。
如有以下代码,其实不是dll文件的源码,而是厂商给的c++例子代码
c++中的结构体申明
1.typedefstruct
2.{
3.unsignedcharPort;
4.unsignedlongId;
5.unsignedcharCtrl;
6.unsignedcharpData[8];
7.}HSCAN_MSG;
c++中的函数申明(一个c++程序引用另一个c++的dll文件)
1.extern"C"int_stdcallHSCAN_SendCANMessage(unsignedcharnDevice,un
signedcharnPort,HSCAN_MSG*msg,intnLength);
c++中的调用:
1.HSCAN_MSGmsg[100];
2......
3.HSCAN_SendCANMessage(m_nDevice,m_nPort,msg,nFrames);
由上述代码可见,msg是个结构体的数组。
下面是我的c#的代码
c#结构体申明:[c-sharp]viewplaincopy
1.[StructLayout(LayoutKind.Sequential)]
2.publicstructHSCAN_MSG
3.{
4.
//UnmanagedType.ByValArray,[MarshalAs(UnmanagedType.U1)]这
个非常重要,就是申明对应类型和长度的
5.[MarshalAs(UnmanagedType.U1)]
6.publicbytePort;
7.[MarshalAs(UnmanagedType.U4)]
8.publicuintnId;
9.[MarshalAs(UnmanagedType.U1)]
10.publicbytenCtrl;
11.[MarshalAs(UnmanagedType.ByValArray,SizeConst=8)]
12.publicbyte[]pData;
13.};
c#函数申明
1.[DllImport("HS2106API.dll")]
2.publicstaticexternintHSCAN_SendCANMessage(
3.bytenDevice,bytenPort,HSCAN_MSG[]pMsg,intnLength);
C#函数调用
1.HSCAN_MSG[]msg=newHSCAN_MSG[1];//发送缓冲区大小可
根据需要设置;2.for(intyy=0;yy 3.{ 4.msg[yy]=newHSCAN_MSG(); 5.} 6.//...结构体中的成员的实例化略 7.HSCAN_SendCANMessage(0x0,0x0,msg,1) 那些只能用指针不能用结构体和类的地方 c++中的结构体申明1.typedefstruct 2.{ 3.unsignedcharPort; 4.unsignedlongId; 5.unsignedcharCtrl; 6.unsignedcharpData[8]; 7.}HSCAN_MSG; c++中的函数申明(一个c++程序引用另一个c++的dll文件) 1.extern"C"int_stdcallHSCAN_SendCANMessage(unsignedchar nDevice,unsignedcharnPort,HSCAN_MSG*msg,intnLength); c#中的结构体申明: 1.[StructLayout(LayoutKind.Sequential)] 2.publicstructHSCAN_MSG 3.{ 4.[MarshalAs(UnmanagedType.U1)] 5.publicbytePort; 6./// 7.///节点标识,nEFF=1时(扩展帧),为29位nEFF=0(标准 帧)时,为11位; 8./// 9.[MarshalAs(UnmanagedType.U4)] 10.publicuintnId; 11.[MarshalAs(UnmanagedType.U1)] 12.publicbytenCtrl; 13.[MarshalAs(UnmanagedType.ByValArray,SizeConst=8)] 14.publicbyte[]pData; 15.}; c#函数的调用:包含使用指针IntPtr替代结构体数组和读取IntPtr的方法 1.HSCAN_MSG[]msg1=newHSCAN_MSG[10]; 2.for(inti=0;i 3.{ 4.msg1[i]=newHSCAN_MSG(); 5.msg1[i].pData=newbyte[8];6.} 7.IntPtr[]ptArray=newIntPtr[1]; 8.ptArray[0]=Marshal.AllocHGlobal(Marshal.SizeOf(typeof (HSCAN_MSG))*10); 9.IntPtrpt=Marshal.AllocHGlobal(Marshal.SizeOf(typeof (HSCAN_MSG))); 10.Marshal.Copy(ptArray,0,pt,1); 11. 12.intcount=HSCAN_ReadCANMessage(0x0,0,pt,10); 13. 14.textBoxStatus.Text+="/r/n"+"读取0口: "+count.ToString()+"帧数据"; 15.for(intj=0;j<10;j++) 16.{ 17.msg1[j]= 18.(HSCAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt+j *Marshal.SizeOf(typeof(HSCAN_MSG))) 19.,typeof(HSCAN_MSG)); 20.textBoxStatus.Text+="/r/n收到0口 "+Convert.ToByte(msg1[j].pData[0]).ToString() 21.+"|"+Convert.ToByte(msg1[j].pData[1]).ToString() 22.+"|"+Convert.ToByte(msg1[j].pData[2]).ToString() 23.+"|"+Convert.ToByte(msg1[j].pData[3]).ToString() 24.+"|"+Convert.ToByte(msg1[j].pData[4]).ToString() 25.+"|"+Convert.ToByte(msg1[j].pData[5]).ToString() 26.+"|"+Convert.ToByte(msg1[j].pData[6]).ToString() 27.+"|"+Convert.ToByte(msg1[j].pData[7]).ToString();