函式名字改編

2021-07-13 19:19:35 字數 2278 閱讀 5510

使用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匯出函式名稱改編的解決方法

分類 c c 程式設計學習 vc ms 2011 05 26 15 04 1437人閱讀收藏 舉報dll delphi api編譯器 pascal winapi 1.dll編譯後匯出函式名稱改編 在編寫乙個dll後,為了能被別的程式呼叫,需要將被使用的函式匯出 但是一般的編譯器都會將到處函式名稱改編...

DLL匯出函式名稱改編的解決方法

1.dll編譯後匯出函式名稱改編 在編寫乙個dll後,為了能被別的程式呼叫,需要將被使用的函式匯出 但是一般的編譯器都會將到處函式名稱改編 例如 在vc中新建乙個空的win32 dll工程,然後新增下面的檔案 cpp view plain copy ifdef dll api declspec dl...

C 函式名字的隱藏 重寫 過載 重定義

概要 c 中經常出現函式名字一樣,但引數列表或返回值不同的函式,要搞清楚函式的正確呼叫關係,需理清三個概念 重寫 override 過載 overload 重定義 redefine 一 三個基本概念 1 重定義 redefine 派生類對基類的成員函式重新定義,即派生類定義了某個函式,該函式的名字與...