dll函式的匯出名的問題

2021-06-16 06:16:42 字數 2398 閱讀 7549

使用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   add   subtract 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 檔案中的作用一樣。

我試了試,覺得最好的方法還是新建乙個def檔案,新增到工程中裡面的書寫格式為等號中間的部分

********************

library "dllname"

exports

start = start

********************==

其中dllname是你要生成的dll檔名,

第乙個start是你想看到的到處函式名,

第二個start是你的dll中申明的那個函式名,其中第二個一定是你原始檔中有的,第乙個可以修改,如果第乙個和第二個不等,會有兩個一樣位址但名字不同的匯出函式,這些都可以用c++6.0的depends工具檢視。

檢視dll的匯出函式

以下摘自msdn 選項由選項說明符 短劃線 或者正斜槓 後跟選項的名稱組成。選項名不能縮寫。某些選項帶引數,引數在冒號 後指定。在選項規範內不允許有空格或製表符。使用乙個或多個空格或製表符來分隔命令列中的選項規範。選項名及其關鍵字或檔名引數不區分大小寫。大多數選項適用於所有二進位制檔案 少數選項僅適...

DLL匯出函式

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

DLL匯出函式

dll匯出的函式 和 匯出類在呼叫時,有些區別,這裡暫時不講,直說簡單的匯出函式 include stdafx.h include mathdll.h pragma comment lib,mathdll.lib 你也可以在專案屬性中設定庫的鏈結 int main 在標頭檔案或是包含標頭檔案下面新增...