關於Dll 匯出函式名 ZZ

2021-05-23 06:56:19 字數 2279 閱讀 7451

使用dependency看dll的匯出函式的名字,會發現有一些有意思的東西,這大多是和編譯dll時候指定dll匯出函式的匯出符有關係。

//當你使用extern "c"的情況下:  

__stdcall會使匯出函式名字前面加乙個下劃線,後面加乙個@再加上引數的位元組數,比如_fun@4就是4個位元組 

__fastcall類似__stdcall,不過前面沒有下劃線,_fastcall應該前面還有乙個@,比如@loadadir@4

__cdecl則是前面僅僅有乙個下劃線

如果不用extern "c"話則使用c++命名機制,涉及到c++ name mangling,比較複雜,編譯器之間也不太一樣。

另外,__declspec(dllexport)僅會對__cdecl進行處理,去掉前面的下劃線(對於一般全域性函式來說預設就是__cdecl),而對於其他兩種不會處理。

//extern "c"的作用是(防止c++編譯器的「名字破壞」特性),使編譯器按照c的方式生成函式名,c的方式實際的函式名和你寫的一樣。如果沒有這個,則按照c++的方式生成函式名,這樣實際的函式名(loadlibrary方式getprocaddress傳入的函式名)和你寫得函式名不一樣,這樣你用loadlibrary、getprocaddress這種方式呼叫dll就不成功。  

但是用引入庫(*.lib)的方式呼叫,則編譯器自動轉換函式名,所以總是沒有問題。  

//我們知道為了讓dll匯出一些函式,需要在每乙個將要被匯出的函式前面新增識別符號:_declspec(dllexport)。例如在dll中可以匯出這樣的函式(方法)

#define dll1_api _declspec(dllexport)

dll1_api int add(int a,int b)

現在我們解決名字改編問題,c++編譯器在生成dll時,會對匯出的函式進行名字改編,並且不同的編譯器使用的改編規則不一樣,因此改編後的名字也是不同的。這樣,如果利用不同編譯器分別生成dll和訪問dll的客戶端程式,後者在訪問該dll的匯出函式時就會出現問題。如上例中函式add在c++編譯器改編後的名字是?add@@yahhh@z。我們希望編譯後的名字不發生改變,這裡有幾種方法。

第一種是定義匯出函式時加上限定符:extern "c"

#define dll1_api extern "c" _declspec(dllexport)

但extern "c"只解決了c和c++語方之間呼叫的問題,它只能用於匯出全域性函式這種情況而不能匯出乙個類的成員函式。另外如果匯出函式的呼叫約定發生改變,即使使用了extern "c",編譯後的函式名還是會發生改變。比如我們加入_stdcall關鍵字說明呼叫約定為c呼叫約定(標準呼叫約定,也就是winapi呼叫約定)。

#define dll1_api extern "c" _declspec(dllexport)

dll1_api int _stdcall add(int a,int b)

編譯後函式名add改編成了_add@8

第二種方法是通過乙個稱為模組定義檔案def來解決。

library dllname

exports

addsubtract

library 用來指定動態鏈結庫內部名稱。該名稱與生成的動態鏈結庫名一定在匹配,這句**不是必須的。exports說明了dll將要匯出的函式,以及為這些匯出函式指定的符號名。

通過第二種方法模組定義檔案的方式dll編譯後匯出函式名不會發生改變。

//傳統的匯出 dll 函式的方法是使用模組定義檔案 (.def),visual c++ 提供了更簡潔方便的方法,即 「__declspec(dllexport)」 關鍵字,例如:

__declspec(dllexport) int __stdcall myexportfunction(int itest);

但是通過檢視工具我們可以發現,dll 匯出的函式名字實際上是 _myexportfunction@4。還好,vc 提供了乙個預處理指示符 「#pragma」 來指定鏈結選項,可以通過它達到我們的目的,如下:

#pragma comment(linker, "/export:myexportfunction=_myexportfunction@4")

這樣再看,就會發現匯出的函式名字已經成為了想要的myexportfunction。

終於知道了,應該把函式前面的 __declspec() 修飾去掉,也就是說,只需要第二條 pragma 指令即可。而且還可以使如下形式:

#pragma comment(linker, "/export:myexportfunction=_myexportfunction@4,private")

private 的作用與其在 def 檔案中的作用一樣。

dll 匯出函式名的那些事

關鍵字 vc dll 匯出函式 經常使用vc6的dependency檢視dll匯出函式的名字,會發現有dll匯出函式的名字有時大不相同,導致不同的原因大多是和編譯dll時候指定dll匯出函式的界定符有關係。vc 支援兩種語言 即c c 這也是造成dll匯出函式差異的根源 我們用vs2008新建個dl...

dll 匯出函式名的那些事

經常使用vc6的dependency檢視dll匯出函式的名字,會發現有dll匯出函式的名字有時大不相同,導致不同的原因大多是和編譯dll時候指定dll匯出函式的界定符有關係。vc 支援兩種語言 即c c 這也是造成dll匯出函式差異的根源 我們用vs2008新建個dll工程,工程名為 testdll...

dll 匯出函式名的那些事

經常使用vc6的dependency檢視dll匯出函式的名字,會發現有dll匯出函式的名字有時大不相同,導致不同的原因大多是和編譯dll時候指定dll匯出函式的界定符有關係。vc 支援兩種語言 即c c 這也是造成dll匯出函式差異的根源 我們用vs2008新建個dll工程,工程名為 testdll...