1、最近做專案遇到,c#呼叫c++dll裡的函式需要傳遞結構體引數,發現這個並不是簡單的在c#裡定義相應的結構體就可以的,下面以乙個例子來說明解決的辦法,c++中的函式和結構體如下:
uint msec_set_igr_gen_cfg(int port, igr_gen_t *igr_gen)
typedef struct igr_gen_t;
在c#中 首先需要使用dllimport將相應的c++dll load進來,然後定義相應的結構體,具體如下:
[dllimport("..\\debug\\mgd_macsec.dll")]
private static extern uint32 msec_set_igr_gen_cfg(int port, intptr igr_gen);
結構體定義:
[structlayout(layoutkind.sequential)]
public class igr_gen_t
} ;
在**中具體引用函式時如下所示,
intptr ptr = marshal.allochglobal(marshal.sizeof(igr_gen));
marshal.structuretoptr(igr_gen, ptr, false);
uint32 ret = _msec_set_igr_gen_cfg(port, ptr);
igr_gen = (igr_gen_t)marshal.ptrtostructure(ptr, typeof(igr_gen_t));
marshal.freehglobal(ptr);
return ret;
從以上步驟可以看出,結構體引數的傳遞需要marshal做輔助做相應的轉化,以intptr的方式傳輸結構體引數。
2、還存在另外一種情況,是結構體中巢狀有結構體時需要做一些特殊處理,具體如下:
結構體typedef struct act_fld;
typedef struct lkup_t;
c++ 函式
uint msec_port_set_egr_entry (in int port, in int ent_num, in lkup_t *egr_lkup)
c#在呼叫時首先將相應dll import進來,進行相應結構體的定義和相應函式的宣告,具體如下:
[dllimport("..\\debug\\mgd_macsec.dll")]
private static extern uint32 msec_set_igr_gen_cfg(int port, intptr igr_gen);
[structlayout(layoutkind.sequential)]
public class act_fld
} [structlayout(layoutkind.sequential)]
public class lkup_t
} 具體在**中引用時如下所示:
intptr egr_lkup_ptr = marshal.allochglobal(marshal.sizeof(egr_lkup));
marshal.structuretoptr(egr_lkup, egr_lkup_ptr, false);
uint ret = _msec_port_set_egr_entry(port, ent_num, egr_lkup_ptr);
egr_lkup = (lkup_t)marshal.ptrtostructure(egr_lkup_ptr, typeof(lkup_t));
marshal.freehglobal(egr_lkup_ptr);
另外列舉(enum)引數傳遞時類似於int型,只需在c#裡定義相應的列舉提即可,不需做相應轉化,在此不再給出具體方法。
另,c++ dll要想被c#所使用,需要進行設定,支援通用語言,具體如下圖所示:(common language runtime support選項)
c#呼叫c++dll檔案是一件很麻煩的事情,首先面臨的是資料型別轉換的問題,相信經常做c#開發的都和我一樣把學校的那點c++底子都忘光了吧(語言特性類)。
網上有一大堆得轉換對應表,也有一大堆的轉換例項,但是都沒有強調乙個更重要的問題,就是c#資料型別和c++資料型別佔記憶體長度的對應關係。
如果dll檔案中只包含一些基礎型別,那這個問題可能可以被忽略,但是如果是組合型別(這個叫法也許不妥),如結構體、類型別等,在其中的成員變數的長度的申明正確與否將決定你對dll檔案呼叫的成敗。
如有以下**,其實不是dll檔案的原始碼,而是廠商給的c++例子**
c++中的結構體申明
typedef struct
hscan_msg;
c++中的函式申明(乙個c++程式引用另乙個c++的dll檔案)
extern "c" int _stdcall hscan_sendcanmessage(unsigned char ndevice,unsigned char nport,hscan_msg *msg,int nlength);
c++中的呼叫:
....
hscan_msg msg[100];
.....
hscan_sendcanmessage(m_ndevice,m_nport,msg,nframes);
由上述**可見,msg是個結構體的陣列。
下面是我的c#的**
c#結構體申明:(申明成)
[structlayout(layoutkind.sequential)]
public struct hscan_msg
; c#函式申明
[dllimport("hs2106api.dll")]
public static extern int hscan_sendcanmessage(
byte ndevice, byte nport, hscan_msg pmsg, int nlength);
c#函式呼叫
hscan_msg msg = new hscan_msg[1]; //傳送緩衝區大小可根據需要設定;
for (int yy = 0; yy < msg.length; yy++)
//...結構體中的成員的例項化略
hscan_sendcanmessage(0x0, 0x0, msg, 1)
那些只能用指標不能用結構體和類的地方
c++中的結構體申明
typedef struct
hscan_msg;
c++中的函式申明(乙個c++程式引用另乙個c++的dll檔案)
extern "c" int _stdcall hscan_sendcanmessage(unsigned char ndevice,unsigned char nport,hscan_msg *msg,int nlength);
c#中的結構體申明:
[structlayout(layoutkind.sequential)]
public struct hscan_msg
; c#函式的呼叫:包含使用指標intptr替代結構體陣列和讀取intptr的方法
hscan_msg msg1 = new hscan_msg[10];
for (int i = 0; i < msg1.length; i++)
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() + "幀資料";
for (int j = 0; j < 10; j++)
謝謝你 「sdl2005lyx」 我的c#呼叫c 動態庫dll 是第三方的是乙個準標的,不能被修改。
這個問題我通過5天的攻關,終於解決了。關鍵是 c# 中 public struct wfsresult
這個結構的定義要改變一下:
將原來的
[structlayout(layoutkind.sequential)]
public struct wfsresult
{改為:(關鍵)
[structlayout(layoutkind.explicit)]
public unsafe struct _wfs_result
{這種方式的定義就可以了。
C 呼叫C C 動態庫 封送結構體,結構體陣列
一.結構體的傳遞 cpp define jnaapi extern c declspec dllexport c方式匯出函式 typedef struct osinfo 1.獲取版本資訊 傳遞結構體指標 jnaapi bool getversionptr osinfo info 2.獲取版本資訊 傳...
c c結構體陣列 結構體指標
結構體中自己常常弄不清的。兩個常用的結構體陣列 結構體指標 將自定義的結構體放入到陣列中方便維護 語法 語法 struct 結構體名 陣列名 元素個數 舉例 struct student intmain for int i 0 i 3 i 2 結構體指標 顧名思義就是指向結構體的乙個指標 通過指標訪...
C C 結構體詳解
前面沒有typedef的 最後乙個 後面的都是結構體變數,結構體變數陣列,結構體指標變數,都是變數。有typedef的 最後乙個 後面的都是型別,是可以拿來構建變數的。typedef struct freaarea 定義乙個空閒區說明表結構 elemtype elemtype data elemty...