C 類來封裝C Dll裡的方法

2022-07-07 13:24:12 字數 2807 閱讀 7039

最近幫底層開發的同時用c#重新封裝一下dll,也就是用c#類來封裝c++dll裡的方法,以供使用者使用。

之前也用到過類似的應用,大多數問題都出在型別轉換上,但是這次的應用層出不窮,所以在這裡總結一下,以供自己以後查閱,也希望對大家能夠有所幫助。

首先,重複一下一些基本使用方法。具體的那些方式在這裡就不重複講了,網上很多的。比如

c++ 標頭檔案中的定義:

npd_api int   np_init();

c#中定義函式

[dllimport("npd_api.dll")]

public static extern int np_init();

基本型別轉換見下表(我用到過的):

bstr——stringbuilder

lpctstr ——stringbuilder

lpcwstr ——intptr

handle ——intptr

hwnd ——intptr

char *  ——string

int * ——ref int

int & ——ref int

void * ——intptrs

unsigned char * ——ref byte    

bool ——bool

dword ——uint或int(我用的是uint,沒出過什麼問題)

我的問題來了,長期的經驗教訓我知道了:

1、指標做引數時在c#中一定要使用ref 或out關鍵字,尤其是結構體指標,要不會報記憶體讀取錯誤,即使不報錯資料也是不太對的。呵呵

sipclient_api void winapi sccleanup(sipclient * psip);

[dllimport("sipclient.dll")]

public static extern void sccleanup(ref sipclient psip);

其中sipclient是乙個結構體。 

2、重寫結構體的時候,之前有指明型別長度或陣列長度的地方,也要進行相應的標註,要不也會導致記憶體錯誤。       

typedef struct net_posa_ethernet;

public struct net_posa_ethernet

3、遇到這樣乙個問題,折騰了大半天時間——

最後是在c++那邊做了修改解決的,通過制定模組定義 (.def) 檔案,統一制定匯出函式對應的名稱。返回值為結構體指標的函式用intptr也能使用了。  

sipclient_api sipclient* scinit(const char * reaml,

const char * from_ip, int from_port,

const char * to_ip, int to_port, const char * server_id,

const char * user_id, const char * user_name, void * user_obj_param);

[dllimport("sipclient.dll")]

public static extern intptr scinit(string reaml, string from_ip, int from_port,

string to_ip, int to_port, string server_id,

string user_id, string user_name, intptr user_obj_param);

4、後來還遇到個**函式導致的崩潰問題,又耽誤了大半天時間,下班了還耽擱了會終於找的解決發辦法了。

剛開始同事分析出了崩潰的原因,都是**方式惹的禍,可參見嘗試使用__stdcall,但是還是沒有解決問題

後來實踐證明,程式是很嚴謹的,半點差錯都不能出才不會導致錯誤,思路還是__stdcall,只不過少改了東西,有兩個地方需要改,才能保證不出錯。

參考關鍵就是這兩句話

typedef void (_stdcall *cicicallback) (bool started, void* client,char *message);

將匯出函式修改為:

extern "c" _declspec(dllexport) bool _stdcall test(char* filename, cicicallback callback)

一開始的時候就只修改了定義那,卻忘記了匯出時的修改,差點就放棄了這條解決思路了,不過還好,所謂堅持就是勝利!

5、後來封裝好拿到使用者那裡用,卻總是提示說找不到c++那些dll.

網上一查,初步定位是開發環境引起的,跟環境部署有關係。我們的開發環境是vs2008,而客戶使用的vs2010,通過幾次嘗試,問題終於了。

首先考慮是缺少某些c++必備的執行庫,存在相互依賴關係,所以導致找不到dll。用檢視dependency walker檢視才發現真的是客戶機子上少了一些東西。

但是此路不通,將缺少的那些東西拷貝到可執行程式目錄下,問題依舊沒有解決。但是依舊堅持這條路~

嘗試安裝vcredist_x86.exe,以排除是否還是缺少了某些執行庫的可能,問題依然存在。

後來我想起來之前搜尋問題的時候,看到好像跟dll的releas\debug版本還有關係,所有又嘗試提議讓同事將他們的c++dll改為release版的。

因為專案是多個人一起做了,編譯release版還花了不少時間,不過好歹問題終於解決了!

總結:直接安裝vcredist_x86.exe,所有dll必須使用release版的。如果使用debug版的就必須保證可執行程式目錄下的dll是完整的,缺一不可!

網上詳細的講解也很多,感覺這個總結的很好

做程式就怕出現問題,出現問題就怕不知道原因,知道原因了就好找解決的辦法啦!

原文 :

c 呼叫c dll中的類方法總結

背景 原始 是c form呼叫c 的dll,現因為需要將 搬遷到linux中,需要先將c 的dll轉為c dll,因為c 的form暫時不方便搬遷,需要先轉後的c dll,也就是需要c 呼叫c dll,原來的c 呼叫c dll的呼叫耦合度較高,有對類成員變數和類函式的呼叫,現對呼叫過程進行總結,如果...

c 呼叫C dll 的方法

c 呼叫c dll 的方法 1.新增 using system.runtime.interopservices 2.將dll 放到執行程式的根目錄下 3.c 中可識別的字元為 utf8,在傳輸字元的時候,需要先轉換為utf8,然後再傳輸,要不然中文會識別不了,同樣在返回資料的時候,也需要將utf8轉...

C 呼叫C Dll封裝時遇到的小問題

c 的乙個dll,裡面有個方法,無返回型別,乙個輸出引數 char 兩個輸入引數。呼叫時遇到點小問題,總結一下。錯誤的呼叫1,直接崩潰 dllimport upgradeserverdll.dll public static extern void upgrade getpatchinifile o...