c c 結構體呼叫

2021-06-10 09:08:00 字數 4559 閱讀 9285

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...