將一個函數聲名為導出函數,就是說這個函數要被其他程序調用,即作為DLL的一個對外函數接口。
通常它和extern "C" 合用,形式如下:
extern "C"
{
__declspec(dllexport) RETURN_TYPE FUNCTION()
{
}
}
這是由於在制作DLL導出函數時由於C++存在函數重載,因此__declspec(dllexport) FUNCTION(int,int) 在DLL會被decorate,例如被decorate成為 function_int_int,而且不同的編譯器decorate的方法不同,造成了在用GetProcAddress取得FUNCTION地址時的不便,使用extern "C"時,上述的decorate不會發生,因為C沒有函數重載,如此一來被extern"C"修飾的函數,就不具備重載能力。
二、以下內容摘自MSDN:
“在 32 位編譯器版本中,可以使用__declspec(dllexport) 關鍵字從 DLL 導出數據、函數、類或類成員函數。__declspec(dllexport)將導出指令添加到對象文件(即obj文件),若要導出函數,__declspec(dllexport)關鍵字必須出現在調用約定關鍵字的左邊(如果指定了關鍵字)。例如:
__declspec(dllexport) void __cdecl Function1(void);
若要導出類中的所有公共數據成員和成員函數,關鍵字必須出現在類名的左邊,如下所示:
class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };
生成 DLL 時,通常創建一個包含正在導出的函數原型和/或類的頭文件,並將__declspec(dllexport)添加到頭文件中的聲明。
若要提高代碼的可讀性,請為__declspec(dllexport)定義一個宏並對正在導出的每個符號使用該宏:
#define DllExport __declspec( dllexport ) ”
三、__declspec(dllexport) 與 .def
模塊定義 (.def) 文件是包含一個或多個描述各種 DLL 屬性的 Module 語句的文本文件。
1、二者的目的都是將公共符號導入到應用程序中或從 DLL 導出函數。
2、添加 __declspec(dllexport)是為了提供不使用.def文件從 .EXE 或 .DLL 導出函數的簡單方法。
3、如果不使用 __declspec (dllimport) 或 __declspec(dllexport) 導出 DLL 函數,則 DLL 需要.def文件。
4、並不是任何時候選擇添加 __declspec(dllexport)而放棄.def的方式都是好的。如果DLL是提供給VC++用戶使用的,只需要把編譯DLL時產生的.lib提供給用戶,它可以很輕松地調用你的DLL。但是如果DLL是供VB、PB、Delphi用戶使用的,那么會產生一個小麻煩。因為VC++對於__declspec(dllexport) 聲明的函數會進行名稱轉換,如下面的函數:
__declspec(dllexport) int __stdcall IsWinNT()
會轉換為IsWinNT@0,這樣你在VB中必須這樣聲明:
Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long
@的后面的數由於參數類型不同而可能不同。這顯然不太方便。所以如果要想避免這種轉換,就要使用.def文件方式。