1. 程式人生 > >C#呼叫c++Dll結構體陣列指標的問題

C#呼叫c++Dll結構體陣列指標的問題

C#呼叫c++dll檔案是一件很麻煩的事情,首先面臨的是資料型別轉換的問題,相信經常做c#開發的都和我一樣把學校的那點c++底子都忘光了吧(語言特性類)。

網上有一大堆得轉換對應表,也有一大堆的轉換例項,但是都沒有強調一個更重要的問題,就是c#資料型別和c++資料型別佔記憶體長度的對應關係。

    如果dll檔案中只包含一些基礎型別,那這個問題可能可以被忽略,但是如果是組合型別(這個叫法也許不妥),如結構體、類型別等,在其中的成員變數的長度的申明正確與否將決定你對dll檔案呼叫的成敗。

如有以下程式碼,其實不是dll檔案的原始碼,而是廠商給的c++例子程式碼

  c++中的結構體申明

  1. typedef struct
  2. {  
  3.   unsigned char Port;  
  4.   unsigned long Id;  
  5.   unsigned char Ctrl;  
  6.   unsigned char pData[8];  
  7. }HSCAN_MSG;  
 

c++中的函式申明(一個c++程式引用另一個c++的dll檔案)

  1. extern"C"int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength);  
 

c++中的呼叫:

  1. ....  
  2. HSCAN_MSG msg[100];  
  3. .....  
  4. HSCAN_SendCANMessage(m_nDevice,m_nPort,msg,nFrames);  
 

由上述程式碼可見,msg是個結構體的陣列。

下面是我的c#的程式碼

c#結構體申明:(申明成)

  1. [StructLayout(LayoutKind.Sequential)]  
  2.    publicstruct HSCAN_MSG  
  3.    {  
  4.     // UnmanagedType.ByValArray, [MarshalAs(UnmanagedType.U1)]這個非常重要,就是申明對應型別和長度的
  5.    [MarshalAs(UnmanagedType.U1)]  
  6.    publicbyte Port;  
  7.    [MarshalAs(UnmanagedType.U4)]  
  8.    publicuint nId;  
  9.    [MarshalAs(UnmanagedType.U1)]  
  10.    publicbyte nCtrl;  
  11.    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]  
  12.    publicbyte[] pData;  
  13.    };  
 

c#函式申明

  1. [DllImport("HS2106API.dll")]  
  2.    publicstaticexternint HSCAN_SendCANMessage(  
  3.    byte nDevice, byte nPort, HSCAN_MSG[] pMsg, int nLength);  
 

C#函式呼叫

  1. HSCAN_MSG[] msg = new HSCAN_MSG[1]; //傳送緩衝區大小可根據需要設定;
  2.    for (int yy = 0; yy < msg.Length; yy++)  
  3.    {  
  4.    msg[yy] = new HSCAN_MSG();  
  5.    }  
  6.     //...結構體中的成員的例項化略
  7.     HSCAN_SendCANMessage(0x0, 0x0, msg, 1)  
 

那些只能用指標不能用結構體和類的地方

c++中的結構體申明

  1. typedef struct
  2. {  
  3.   unsigned char Port;  
  4.   unsigned long Id;  
  5.   unsigned char Ctrl;  
  6.   unsigned char pData[8];  
  7. }HSCAN_MSG;  
 

c++中的函式申明(一個c++程式引用另一個c++的dll檔案)

  1. extern"C"int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength);  
 

c#中的結構體申明:

  1. [StructLayout(LayoutKind.Sequential)]  
  2.    publicstruct HSCAN_MSG  
  3.    {  
  4.    [MarshalAs(UnmanagedType.U1)]  
  5.    publicbyte Port;  
  6.    /// <summary>
  7.    /// 節點標識,nEFF=1 時(擴充套件幀),為29 位nEFF=0(標準幀)時,為11 位;
  8.    /// </summary>
  9.    [MarshalAs(UnmanagedType.U4)]  
  10.    publicuint nId;  
  11.    [MarshalAs(UnmanagedType.U1)]  
  12.    publicbyte nCtrl;  
  13.    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]  
  14.    publicbyte[] pData;  
  15.    };  
 

c#函式的呼叫:包含使用指標IntPtr替代結構體陣列和讀取IntPtr的方法

  1. HSCAN_MSG[] msg1 = new HSCAN_MSG[10];  
  2.    for (int i = 0; i < msg1.Length; i++)  
  3.    {  
  4.    msg1[i] = new HSCAN_MSG();  
  5.    msg1[i].pData = newbyte[8];  
  6.    }  
  7.    IntPtr[] ptArray = new IntPtr[1];  
  8.    ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)) * 10);  
  9.    IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)));  
  10.    Marshal.Copy(ptArray, 0, pt, 1);  
  11.    int count = HSCAN_ReadCANMessage(0x0, 0,pt, 10);  
  12.    textBoxStatus.Text += "/r/n" + "讀取0口:" + count.ToString() + "幀資料";  
  13.    for (int j = 0; j < 10; j++)  
  14.    {  
  15.    msg1[j] =  
  16.    (HSCAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt+ j * Marshal.SizeOf(typeof(HSCAN_MSG)))  
  17.    , typeof(HSCAN_MSG));  
  18.    textBoxStatus.Text += "/r/n收到0口" + Convert.ToByte(msg1[j].pData[0]).ToString()  
  19.    + "|" + Convert.ToByte(msg1[j].pData[1]).ToString()  
  20.    + "|" + Convert.ToByte(msg1[j].pData[2]).ToString()  
  21.    + "|" + Convert.ToByte(msg1[j].pData[3]).ToString()  
  22.    + "|" + Convert.ToByte(msg1[j].pData[4]).ToString()  
  23.    + "|" + Convert.ToByte(msg1[j].pData[5]).ToString()  
  24.    + "|" + Convert.ToByte(msg1[j].pData[6]).ToString()  
  25.    + "|" + Convert.ToByte(msg1[j].pData[7]).ToString();  
  26.    }  
 

相關推薦

C#呼叫c++Dll結構陣列指標的問題

C#呼叫c++dll檔案是一件很麻煩的事情,首先面臨的是資料型別轉換的問題,相信經常做c#開發的都和我一樣把學校的那點c++底子都忘光了吧(語言特性類)。 網上有一大堆得轉換對應表,也有一大堆的轉換例項,但是都沒有強調一個更重要的問題,就是c#資料型別和c++資料型別佔

C語言】用結構陣列指標完成:有三個學生資訊,存放在結構陣列中,要求輸出全部資訊

//用結構體陣列指標完成:有三個學生資訊,存放在結構體陣列中,要求輸出全部資訊 #include <stdio.h> struct Stu { int num; char name[2

c語言結構陣列指標

#include<stdio.h> #define N 3 struct student { long int num; char name[20]; float score[3]; float aver; }; int main() {

C/C++動態自定義結構陣列例項鍛鍊-學生成績排序

/************************************************************************/ /* 本程式是對動態記憶體、動態陣列、結構體、函式的綜合應用。 */ /***********************

C語言】用結構陣列完成:有5個學生(包括學號,姓名,成績),要求按照成績高低輸出學生資訊.

//用結構體陣列完成:有5個學生(包括學號,姓名,成績),要求按照成績高低輸出學生資訊 #include <stdio.h> struct Stu { int num; char na

C語言_指向結構指標_plusC14.4

#include<stdio.h> #define LEN 20 struct name {char first[LEN];char last[LEN]; }; struct guy {struct name handle;char favfood[LEN];c

c#呼叫C/C++ DLL,傳入指標陣列(指標指向自定的結構)

來源:http://bbs.csdn.net/topics/380165851 依靠以下文章:解決問題。 、、、、、、、、、、、、、、、、、、、、 可以用Marshal.StruectToPtr哦。 、、、、、、、、、、、、、、 [StructLayout(Layo

結構指標作函式引數(C# 呼叫C++ 的DLL

1、C++結構體定義:   #pragma pack(1)  struct Person  {      #define Count_favoriteNumbers 6        int id;        fl

C# 呼叫dll 封送結構 結構陣列

一. 結構體的傳遞 cpp 程式碼 #define JNAAPI extern "C" __declspec(dllexport) // C方式匯出函式 typedef struct { int osVersion; int majorVe

C#呼叫C++ 平臺呼叫P/Invoke 結構--含有內建資料型別的一維、二維陣列、字串指標【六】

【1】結構體中含有內建資料型別的一維陣列 C++程式碼: typedef struct _testStru3 { int iValArrp[30]; WCHAR szChArr[30];

轉--C#呼叫C++DLL傳遞結構陣列的終極解決方案

在專案開發時,要呼叫C++封裝的DLL,普通的型別C#上一般都對應,只要用DllImport傳入從DLL中引入函式就可以了。但是當傳遞的是結構體、結構體陣列或者結構體指標的時候,就會發現C#上沒有型別可以對應。這時怎麼辦,第一反應是C#也定義結構體,然後當成引數傳弟。然而,當

C#呼叫C/C++動態庫 封送結構,結構陣列

一. 結構體的傳遞 Cpp程式碼    #define JNAAPI extern "C" __declspec(dllexport) // C方式匯出函式   typedef struct       {         int osVersion;  

C語言 一個例子說明結構變數,結構陣列結構指標

輸入三個學生的個人資訊 包含學號 姓名和三門學科的成績 輸出平均成績最高的學生的學號 姓名 各科成績以及平均成績 程式碼如下(譚浩強c程式設計的例子) #include<stdio.h> struct Student {int num;

5. C 結構 陣列指標 初始化 與 記憶體釋放

結構體如下: struct student{ Int num; Char* name; } Tom,*Lily; 1.如果定義成Tom的形式,不需要為結構體分配記憶體,但是需要對name

c語言指向結構陣列指標

 c指標變數可以指向一個結構陣列,這時結構指標變數的值是整個結構陣列的首地址。結構指標變數也可指向結構陣列的一個元素,這時結構指標變數的值是該結構陣列元素的首地址。設ps為指向結構陣列的指標變數,則ps也指向該結構陣列的0號元素,ps+1指向1號元素,ps+i則指向i號

第22節 C語言結構結構巢狀、結構指標結構陣列的程式碼實現

結構體 #include <stdio.h> //第一步 struct Student { //學號 int no; //姓名 char name[20]; //性別 char

結構陣列,結構指標 (C,隨筆)

#include<stdlib.h> struct S { int num; }; struct S s; struct S ss[5]; #include<stdio.h>

C#呼叫C++ 平臺呼叫P/Invoke 結構--輸入輸出引數、返回值、返出值、結構陣列作為引數【五】

【1】結構體作為輸入輸出引數 C++程式碼: typedef struct _testStru1 { int iVal; char cVal; __int64 llVal; }testS

C++的陣列結構指標三種複合型別知識點小總結

陣列、結構體、指標是C++的3種複合型別。陣列可以在一個數據物件中儲存多個不同型別的值,通過使用索引或下標,可以訪問陣列中的各個元素。結構體可以將多個不同型別的值儲存在同一個資料物件中,可以使用成員關

C語言——結構指標引用&結構陣列指標引用

接下來,程式的控制權交給Mutiline函式,進入函式Mutiline。在程式進入函式Mutiline之後,pPoints 指向oPoints的首地址,跟蹤程式表明此時變數pPoints的當前值為0X0F82。另外,由於陣列第一個元素oPoints[0]的地址與陣列的首地址相同。亦可以理解為此時pPoints