編寫C 呼叫的C DLL

2021-05-25 16:16:53 字數 2916 閱讀 4746

最近一段時間,經常遇到這些問題,前一陣子研究了一下,沒有記下來,沒想到最近研究又有些不記得了,今天把它寫下來以備忘。

一般我們提供給其他語言呼叫的dll,都是用c或者c++編寫,然後封裝。我這邊也是採用的c++。

首先有幾個注意點:

1、如果功能很簡單,或者不使用第三方庫(如mfc自帶的庫),建立乙個win32的控制台程式就可以了,然後把專案生成改為dll。值得一提的是,**生成裡面

執行時庫分四種:

(1)多執行緒mtd(靜態庫,編譯之後,你的lib帶有除錯功能)——> debug時用

(2)多執行緒mt(靜態庫,沒有除錯功能)                           ——> release時用

(3)多執行緒dll mtd(動態庫,帶有除錯功能)                  ——> debug時用

(4)多執行緒dll mt(動態庫,沒有有除錯功能)。              ——> release時用s

既然封裝dll,那除錯的時候用(3),發布的時候用(4)。

2、設定為匯出函式,並採用c風格。函式前加extern "c" __declspec(dllexport)。定義函式在退出前自己清空堆疊,在函式前加__stdcall。

如extern "c" __declspec(dllexport) int __stdcall add(int x,int y);

具備上述條件時,生成的dll就含有匯出函式的功能了,不過此時dll中的函式名稱不是規則的,使用編譯器自定義的,可能是這樣乙個名字_add@20,具體的可以用vs的depends工具檢視一下。

3、把匯出函式名稱變為標準名稱,需加模組定義檔案,就是.def檔案。

內容如下:(需要注釋,前面加分號就可以了,注釋需要單獨行)

library "test"

exports

;add函式

adds

library 庫名稱

exports 需要匯出的各個函式名稱

重新編譯之後,再用depends工具看一下,函式已經變成標準add,而不是_add@20。這個在動態載入時很有用,特別是在getprocaddress函式尋找入庫函式的時候。

4、c#呼叫c++ dll,介紹兩種方法

(1)靜態載入

[dllimport("test.dll", entrypoint = "add")]

public int add(int x,int y);//與dll中一致 

注意如果需要返回字串可以這樣

c++中

int getstring(const char* source,char* dest);

c#中int getstring(string source,stringbuilder sbr);

切記呼叫的時候給stringbuilder 分配空間,否則會報錯。

如dest 長度為10,可以這樣。

stringbuilder sbr=new stringbuilder(10);

getstring("hello",sbr);

如果你希望c++的dll還能被vb等語言呼叫,建議將字串寫成com的形式 如

c++中

int getstring(bstr source,bstr dest);//bstr就是乙個com形式的字元陣列,相當於字串

c#中int getstring(string source,stringbuilder sbr);

vb中declare function getstring lib "test.dll" (byval source as string, byval dest as string) as integer;

(2)動態載入

[dllimport("kernel32.dll")]

private extern static intptr loadlibrary(string path);//path 就是dll路徑 返回結果為0表示失敗。

[dllimport("kernel32.dll")]

private extern static intptr getprocaddress(intptr lib, string funcname);//lib是loadlibrary返回的控制代碼,funcname 是函式名稱 返回結果為0標識失敗。

[dllimport("kernel32.dll")]

private extern static bool freelibrary(intptr lib);

//宣告委託

delegate int add(int x,int y);

//使用動態載入

intptr hlib = loadlibrary(dllpath);//載入函式

intptr apifunction = getprocaddress(hlib, apiname);//獲取函式位址

int i = marshal.getlastwin32error();

if (apifunction.toint32() == 0)//0表示函式沒找到

return null;

//獲取函式介面,相當於函式指標

add add = (delegate)marshal.getdelegateforfunctionpointer(apifunction, typeof(add)) as add;          

//呼叫函式

add(1,2);

//釋放控制代碼

freelibrary(hlib );

最後,1)c++在返回字串時,切記最後新增/0,不然在c#等中呼叫,會顯示部分亂碼。    

2)c++動態申請的記憶體,需在出函式之前就必須釋放,否則會報意想不到的錯誤。比如記憶體寫入錯誤等等。

C 呼叫C DLL的方式

動態鏈結庫 dll 是乙個包含可由多個程式同時使用的 和資料的庫,dll不是可執行檔案。可以說在windows作業系統中隨處可見,開啟主分割槽盤下的system32。在一些專案中,如果有大量運算或者涉及大量演算法時通常使用c或c 語言封裝成乙個dll,開放一些介面供其他程式呼叫。下面是寫的乙個簡單的...

c 呼叫C dll 的方法

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

C 呼叫C Dll例程

form1.cs內容 using system using system.windows.forms using system.runtime.interopservices using system.text 申明dll中函式 dllimport kb dll.dll entrypoint inp...