1. 程式人生 > >VC++  DLL 匯出函式

VC++  DLL 匯出函式

經常使用VC6的Dependency檢視DLL匯出函式的名字,會發現有DLL匯出函式的名字有時大不相同,導致不同的原因大多是和編譯DLL時候指定DLL匯出函式的界定符有關係。

VC++支援兩種語言:即C/C++,這也是造成DLL匯出函式差異的根源

我們用VS2008新建個DLL工程,工程名為“TestDLL”

把預設的原始檔字尾 .CPP改為.C(C檔案)

輸入測試程式碼如下:

01 int _stdcall MyFunction(int iVariant)

02 {

03 return 0;

04 }

為了匯出上面這個函式,我們有以下幾個方法:

1. 使用傳統的模組定義檔案 (.def)

新建一個 字尾為.def的文字檔案(這裡建一個TestDll.Def),檔案內容為:

LIBRARY TestDll

EXPORTS

MyFunction

在 Link 時指定輸入依賴檔案:/DEF:"TestDll.Def"

2. Visual C++ 提供的方便方法

在01行的int 前加入 __declspec(dllexport) 關鍵字

通過以上兩種方法,我們就可以匯出MyFunction函式。

我們用Dependency檢視匯出的函式:

第一種方法匯出的函式為:

MyFunction

clip_image002

第二種方法匯出的函式為:

[email protected]

clip_image004

__stdcall會使匯出函式名字前面加一個下劃線,後面加一個@再加上引數的位元組數,比如[email protected]的引數(int iVariant)就是4個位元組
__fastcall與 __stdcall類似,不過前面沒有下劃線,而是一個@,比如@[email protected]
__cdecl則是始函式名。

小結:如果要匯出C檔案中的函式,並且不讓編譯器改動函式名,用def檔案匯出函式。

下面我們來看一下C++檔案

我們用VS2008新建個DLL工程,工程名為“TestDLL”

預設的原始檔字尾為 .CPP (即C++檔案)。

輸入測試程式碼如下:

01 int _stdcall MyFunction(int iVariant)

02 {

03 return 0;

04 }

為了匯出上面這個函式,我們有以下幾個方法:

3. 使用傳統的模組定義檔案 (.def)

新建一個 字尾為.def的文字檔案(這裡建一個TestDll.Def),檔案內容為:

LIBRARY TestDll

EXPORTS

MyFunction

在 Link 時指定輸入依賴檔案:/DEF:"TestDll.Def"

4. Visual C++ 提供的方便方法

在01行的int 前加入 __declspec(dllexport) 關鍵字

通過以上兩種方法,我們就可以匯出MyFunction函式。

我們用Dependency檢視匯出的函式:

第一種方法匯出的函式為:

MyFunction

第二種方法匯出的函式為:

[email protected]@[email protected]

可以看到 第二種方法得到的 匯出函式名 並不是我們想要的,如果在exe中用顯示方法(LoadLibrary、GetProcAddress)呼叫 MyFunction 肯定會失敗。

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

解決這個問題的方法是:

用VC 提供的預處理指示符 “#pragma” 來指定連結選項。

如下:

#pragma comment(linker, "/EXPORT:[email protected]@[email protected]")

這時,就會發現匯出的函式名字表中已經有了我們想要的MyFunction。但我們發現原來的那個 [email protected]@[email protected] 函式還在,這時就可以把 __declspec() 修飾去掉,只需要 pragma 指令即可。

而且還可以使如下形式:

#pragma comment(linker, "/EXPORT:[email protected],PRIVATE")

PRIVATE 的作用與其在 def 檔案中的作用一樣。更多的#pragram請檢視MSDN。

小結:如果要匯出C++檔案中的函式,並且不讓編譯器改動函式名,用def檔案匯出函式。

同時可以用#pragma指令(C 中也可以用)。

總結:

C++編譯器在生成DLL時,會對匯出的函式進行名字改編,並且不同的編譯器使用的改編規則不一樣,因此改編後的名字也是不同的(一般涉及到C++ 中的過載等)。

如果利用不同編譯器分別生成DLL和訪問DLL的exe程式,後者在訪問該DLL的匯出函式時就會出現問題。如上例中函式MyFunction在C++編譯器改編後的名字是[email protected]@[email protected]。我們希望編譯後的名字不發生改變,這裡有幾種方法。

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

LIBRARY TestDll

EXPORTS

MyFunction

LIBRARY 用來指定動態連結庫內部名稱。該名稱與生成的動態連結庫名一定要匹配,這句程式碼不是必須的。

EXPORTS說明了DLL將要匯出的函式,以及為這些匯出函式指定的符號名。

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

如:#define DLLEXPORT_API extern "C" _declspec(dllexport)

但extern "C"只解決了C和C++語方之間呼叫的問題(extern “C” 是告訴編譯器,讓它按C的方式編譯),它只能用於匯出全域性函式這種情況 而不能匯出一個類的成員函式。

同時如果匯出函式的呼叫約定發生改變,即使使用extern "C",編譯後的函式名還是會發生改變。例如上面我們加入_stdcall關鍵字說明呼叫約定(標準呼叫約定,也就是WINAPI呼叫約定)。
#define DLLEXPORT_API extern "C" _declspec(dllexport)
01 DLLEXPORT_API int _stdcall MyFunction(int iVariant)

02 {

03 return 0;

04 }
編譯後函式名MyFunction改編成了[email protected]

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

繪圖1

作者mail:[email protected]

相關推薦

VC++  DLL 匯出函式

經常使用VC6的Dependency檢視DLL匯出函式的名字,會發現有DLL匯出函式的名字有時大不相同,導致不同的原因大多是和編譯DLL時候指定DLL匯出函式的界定符有關係。 VC++支援兩種語言:即C/C++,這也是造成DLL匯出函式差異的根源 我們用VS2008新建

c++ dll匯出函式返回false值C#卻認為是true的處理方法

轉發網址https://stackoverflow.com/questions/1792581/c-from-c-c-function-in-a-dll-returning-false-but-c-sharp-thinks-its-tr 在C++中宣告匯出函式 bool Foo()

Dll 匯出函式那些破事

經常使用VC6的Dependency檢視DLL匯出函式的名字,會發現有DLL匯出函式的名字有時大不相同,導致不同的原因大多是和編譯DLL時候指定DLL匯出函式的界定符有關係。 VC++支援兩種語言:即C/C++,這也是造成DLL匯出函式差異的根源 我們用VS2008新建個DLL工程,工程名為

檢視DLL匯出函式的方法

VS2010中沒有了Depends工具,如何檢視DLL檔案的匯出介面呢? VS2010的操作方法如下: 1. 開啟命令列視窗CMD 2. 執行vcvarsall.bat VS2010 裡vcvarsall.bat是在右鍵VS開啟檔案位置,D:\M

vcdll匯出匯入簡單教程

dll和lib的區別 未完待續 如何匯出dll 查閱msdn官方文件發現,匯出dll有三種方式,一種是使用.def檔案匯出,另一種是在程式碼中使用巨集__declspec(dllexport)匯出,最後一種是配置vc工程的屬性,使用LINK 命令中的

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

1.DLL編譯後匯出函式名稱改編 在編寫一個DLL後,為了能被別的程式呼叫,需要將被使用的函式匯出; 但是一般的編譯器都會將到處函式名稱改編; 例如:在VC中新建一個空的win32 dll工程,然後新增下面的檔案; //dll1.h #ifdef DLL_

VS2010怎麼用Dumpbin來檢視DLL匯出函式

首先,開始->所有程式->Microsoft Visual Studio 2010->Visual Studio Tools ->“Visual Studio 命令提示(2010)” 開啟後輸入 dumpbin -exports D:\C_engin

Dll匯出函式劫持通用方法

問題發現 dll劫持是一種常見的攻擊方法,但是也可以用在不知道程式原始碼的情況下除錯dll的函式。之前在滴水教程的視訊中注意到一個問題,視訊作者演示了一個劫持messagebox函式,列印輸出引數的過程,當時學生提問是否存在一種通用的方法可以劫持所有

dll 匯出函式名的那些事

關鍵字: VC++  DLL  匯出函式  經常使用VC6的Dependency檢視DLL匯出函式的名字,會發現有DLL匯出函式的名字有時大不相同,導致不同的原因大多是和編譯DLL時候指定DLL匯出函式的界定符有關係。 VC++支援兩種語言:即C/C++,這也是造成D

dll匯出函式符號含義

DLL中匯出類成員函式名稱修飾意思解釋大全 2、C++編譯時函式(非類成員函式)名稱修飾 當函式使用__cdecl呼叫約定時,編譯器進行以下工作: 1.以?標識函式名的開始,後跟函式名; 2.函式名後面以@@YA標識開始,後跟返回值和引數表; 3.當函式的返回

使用Dumpbin命令確認dll匯出函式

首先在命令列中進入到VS的安裝目錄下,執行一個名為VCVARS32.bat的批處理程式(對於VS2013來說,該bat檔案位於\VC\bin目錄下),該檔案的作用是用來建立VC++使用的環境資訊。(注意,當在命令列介面執行VCVARS32.bat檔案後,該檔案設定的環境資訊只在當前命令列視窗生效。)

如何檢視DLL檔案的匯出函式宣告

http://blog.csdn.net/uvbs/archive/2006/01/27/589346.aspx Depends.exe 是 Visual C++ 自帶的一個工具。它可能是我們經常使

def檔案 匯出dll過載函式

轉載地址:http://blog.163.com/very_apple/blog/static/27759236201092024110861/ 動態連結庫DLL_Sample.dll DLL_Sample.h: #ifdef TEST_API # define TEST

C#中呼叫C++的dll的引數為指標型別的匯出函式(包括二級指標的情況)

一:首先什麼是IntPtr 先來看看MSDN上說的:用於表示指標或控制代碼的平臺特定型別。這個其實說出了這樣兩個事實,IntPtr 可以用來表示指標或控制代碼、它是一個平臺特定型別。對於它的解釋,這個哥們寫的比較好:It's a class that wraps a

VC和MinGW匯出dll的def和lib(a)檔案

開發十年,就只剩下這套架構體系了! >>>   

C++如何調用C#編寫的 DLL

csharp class 配置 copy pac print pre lec visual 由於C#編繹出來的DLL不是計算機所能直接識別的二進制指令碼,需要CLS進行再解釋,說到這,我想有些朋友應該知道C#項目需要引用C++編寫的DLL時,可以直接引用DLLMPORT來

核心特徵碼搜尋 獲取未匯出函式

無聊寫了下 有Bug 注意下就好啦~ #include "GetUndocumentFunctionAdress.h" #pragma warning(disable : 4047) PVOID GetCallPoint(PVOID pCallPoint) { ULONG

VC 寫shellcode 時函式地址去掉跳轉表

在預設DEBUG/RELEASE模式下函式地址不是最終的函式地址,而是E9 + offset 的形式,這使得直接使用函式地址作為shellcode 起始地址時會出現問題。該怎麼修改編譯選項呢? 在專案屬性中,選擇 “配置屬性” ==> "C/C++" ==> "優化" ==>

DEP引起的DLL函式呼叫失敗

1          什麼是DEP(資料執行保護) 根據微軟官方定義:資料執行保護 (DEP) 是一種有助於防止您的計算機免受病毒和其他安全威脅破壞的安全功能。有害的程式可能會通過試圖執行(也稱為“執行”)

dll匯出方式

在一個dll工程中,想要匯出某些函式,那麼就必須給程式標記清楚,程式才會這樣去做。 如果要想匯出一個函式,那麼,有如下兩種方式: 1、在函式宣告時候,在函式前面加上 __declspec(dllexport),如下: #ifdef __cplusplus extern "C"{ #endif