這篇文章給大家分享的是有關(guān)基于C#如何調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
成都創(chuàng)新互聯(lián)專注于色尼網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供色尼營銷型網(wǎng)站建設(shè),色尼網(wǎng)站制作、色尼網(wǎng)頁設(shè)計、色尼網(wǎng)站官網(wǎng)定制、小程序定制開發(fā)服務(wù),打造色尼網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供色尼網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
C#調(diào)用c++dll文件是一件很麻煩的事情,首先面臨的是數(shù)據(jù)類型轉(zhuǎn)換的問題,相信經(jīng)常做c#開發(fā)的都和我一樣把學校的那點c++底子都忘光了吧(語言特性類)。
網(wǎng)上有一大堆得轉(zhuǎn)換對應(yīng)表,也有一大堆的轉(zhuǎn)換實例,但是都沒有強調(diào)一個更重要的問題,就是c#數(shù)據(jù)類型和c++數(shù)據(jù)類型占內(nèi)存長度的對應(yīng)關(guān)系。
如果dll文件中只包含一些基礎(chǔ)類型,那這個問題可能可以被忽略,但是如果是組合類型(這個叫法也許不妥),如結(jié)構(gòu)體、類類型等,在其中的成員變量的長度的申明正確與否將決定你對dll文件調(diào)用的成敗。
如有以下代碼,其實不是dll文件的源碼,而是廠商給的c++例子代碼
c++中的結(jié)構(gòu)體申明
typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG;
c++中的函數(shù)申明(一個c++程序引用另一個c++的dll文件)
extern "C" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength);
c++中的調(diào)用:
.... HSCAN_MSG msg[100]; ..... HSCAN_SendCANMessage(m_nDevice,m_nPort,msg,nFrames);
由上述代碼可見,msg是個結(jié)構(gòu)體的數(shù)組。
下面是我的c#的代碼
c#結(jié)構(gòu)體申明:(申明成)
[StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { // UnmanagedType.ByValArray, [MarshalAs(UnmanagedType.U1)]這個非常重要,就是申明對應(yīng)類型和長度的 [MarshalAs(UnmanagedType.U1)] public byte Port; [MarshalAs(UnmanagedType.U4)] public uint nId; [MarshalAs(UnmanagedType.U1)] public byte nCtrl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; };
c#函數(shù)申明
[DllImport("HS2106API.dll")] public static extern int HSCAN_SendCANMessage( byte nDevice, byte nPort, HSCAN_MSG[] pMsg, int nLength);
C#函數(shù)調(diào)用
HSCAN_MSG[] msg = new HSCAN_MSG[1]; //發(fā)送緩沖區(qū)大小可根據(jù)需要設(shè)置; for (int yy = 0; yy < msg.Length; yy++) { msg[yy] = new HSCAN_MSG(); } //...結(jié)構(gòu)體中的成員的實例化略 HSCAN_SendCANMessage(0x0, 0x0, msg, 1)
那些只能用指針不能用結(jié)構(gòu)體和類的地方
c++中的結(jié)構(gòu)體申明
typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG;
c++中的函數(shù)申明(一個c++程序引用另一個c++的dll文件)
extern "C" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength);
c#中的結(jié)構(gòu)體申明:
[StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { [MarshalAs(UnmanagedType.U1)] public byte Port; ////// 節(jié)點標識,nEFF=1 時(擴展幀),為29 位nEFF=0(標準幀)時,為11 位; /// [MarshalAs(UnmanagedType.U4)] public uint nId; [MarshalAs(UnmanagedType.U1)] public byte nCtrl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; };
c#函數(shù)的調(diào)用:包含使用指針I(yè)ntPtr替代結(jié)構(gòu)體數(shù)組和讀取IntPtr的方法
HSCAN_MSG[] msg1 = new HSCAN_MSG[10]; for (int i = 0; i < msg1.Length; i++) { msg1[i] = new HSCAN_MSG(); msg1[i].pData = new byte[8]; } IntPtr[] ptArray = new IntPtr[1]; ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)) * 10); IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG))); Marshal.Copy(ptArray, 0, pt, 1); int count = HSCAN_ReadCANMessage(0x0, 0,pt, 10); textBoxStatus.Text += "/r/n" + "讀取0口:" + count.ToString() + "幀數(shù)據(jù)"; for (int j = 0; j < 10; j++) { msg1[j] = (HSCAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt+ j * Marshal.SizeOf(typeof(HSCAN_MSG))) , typeof(HSCAN_MSG)); textBoxStatus.Text += "/r/n收到0口" + Convert.ToByte(msg1[j].pData[0]).ToString() + "|" + Convert.ToByte(msg1[j].pData[1]).ToString() + "|" + Convert.ToByte(msg1[j].pData[2]).ToString() + "|" + Convert.ToByte(msg1[j].pData[3]).ToString() + "|" + Convert.ToByte(msg1[j].pData[4]).ToString() + "|" + Convert.ToByte(msg1[j].pData[5]).ToString() + "|" + Convert.ToByte(msg1[j].pData[6]).ToString() + "|" + Convert.ToByte(msg1[j].pData[7]).ToString(); }
感謝各位的閱讀!關(guān)于“基于C#如何調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!