基于C#調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針的問(wèn)題詳解
C#調(diào)用c++dll文件是一件很麻煩的事情,首先面臨的是數(shù)據(jù)類(lèi)型轉(zhuǎn)換的問(wèn)題,相信經(jīng)常做c#開(kāi)發(fā)的都和我一樣把學(xué)校的那點(diǎn)c++底子都忘光了吧(語(yǔ)言特性類(lèi))。
網(wǎng)上有一大堆得轉(zhuǎn)換對(duì)應(yīng)表,也有一大堆的轉(zhuǎn)換實(shí)例,但是都沒(méi)有強(qiáng)調(diào)一個(gè)更重要的問(wèn)題,就是c#數(shù)據(jù)類(lèi)型和c++數(shù)據(jù)類(lèi)型占內(nèi)存長(zhǎng)度的對(duì)應(yīng)關(guān)系。
如果dll文件中只包含一些基礎(chǔ)類(lèi)型,那這個(gè)問(wèn)題可能可以被忽略,但是如果是組合類(lèi)型(這個(gè)叫法也許不妥),如結(jié)構(gòu)體、類(lèi)類(lèi)型等,在其中的成員變量的長(zhǎng)度的申明正確與否將決定你對(duì)dll文件調(diào)用的成敗。
如有以下代碼,其實(shí)不是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ù)申明(一個(gè)c++程序引用另一個(gè)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);
由上述代碼可見(jiàn),msg是個(gè)結(jié)構(gòu)體的數(shù)組。
下面是我的c#的代碼
c#結(jié)構(gòu)體申明:(申明成)
[StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { // UnmanagedType.ByValArray, [MarshalAs(UnmanagedType.U1)]這個(gè)非常重要,就是申明對(duì)應(yīng)類(lèi)型和長(zhǎ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)體中的成員的實(shí)例化略 HSCAN_SendCANMessage(0x0, 0x0, msg, 1)
那些只能用指針不能用結(jié)構(gòu)體和類(lèi)的地方
c++中的結(jié)構(gòu)體申明
typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG;
c++中的函數(shù)申明(一個(gè)c++程序引用另一個(gè)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; /// <summary> /// 節(jié)點(diǎn)標(biāo)識(shí),nEFF=1 時(shí)(擴(kuò)展幀),為29 位nEFF=0(標(biāo)準(zhǔn)幀)時(shí),為11 位; /// </summary> [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(); }
以上這篇基于C#調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針的問(wèn)題詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- C# 調(diào)用C++寫(xiě)的dll的實(shí)現(xiàn)方法
- C++調(diào)用C#的DLL實(shí)現(xiàn)方法
- C#調(diào)用C++dll方法步驟
- C++與C#互調(diào)dll的實(shí)現(xiàn)步驟
- C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案
- C++調(diào)用C#的DLL程序?qū)崿F(xiàn)方法
- c#調(diào)用c++的DLL的實(shí)現(xiàn)方法
- C#程序調(diào)用C++動(dòng)態(tài)庫(kù)(dll文件)遇到的坑及解決
- C#程序如何調(diào)用C++?dll詳細(xì)教程
- C++項(xiàng)目中調(diào)用C#DLL的三種方式
相關(guān)文章
C# XML與Json之間相互轉(zhuǎn)換實(shí)例詳解
這篇文章主要介紹了C# XML與Json之間相互轉(zhuǎn)換實(shí)例詳解,大家參考使用吧2013-11-11C#把UNICODE編碼轉(zhuǎn)換為GB編碼的實(shí)例
下面小編就為大家?guī)?lái)一篇C#把UNICODE編碼轉(zhuǎn)換為GB編碼的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01C#中私有構(gòu)造函數(shù)的特點(diǎn)和用途實(shí)例解析
這篇文章主要介紹了C#中私有構(gòu)造函數(shù)的特點(diǎn)和用途,需要的朋友可以參考下2014-08-08如何在Mac系統(tǒng)使用Visual Studio Code運(yùn)行Python
這篇文章主要介紹了Mac使用Visual Studio Code運(yùn)行Python環(huán)境的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04c#打印預(yù)覽控件中實(shí)現(xiàn)用鼠標(biāo)移動(dòng)頁(yè)面功能代碼分享
項(xiàng)目中需要實(shí)現(xiàn)以下功能:打印預(yù)覽控件中,可以用鼠標(biāo)拖動(dòng)頁(yè)面,以查看超出顯示范圍之外的部分內(nèi)容,下面就是實(shí)現(xiàn)代碼2013-12-12直接在線預(yù)覽Word、Excel、TXT文件之ASP.NET
這篇文章主要用asp.net技術(shù)實(shí)現(xiàn)直接在線預(yù)覽word、excel、txt文件,有需要的朋友可以參考下2015-08-08