DLL 匯出方法(兩種)
.def 檔案必須至少包含下列模組定義語句:
-
檔案中的第一個語句必須是 LIBRARY 語句。 此語句將 .def 檔案標識為屬於 DLL。 LIBRARY 語句的後面是 DLL 的名稱。 連結器將此名稱放到 DLL 的匯入庫中。
-
EXPORTS 語句列出名稱,可能的話還會列出 DLL 匯出函式的序號值。 通過在函式名的後面加上 @ 符和一個數字,給函式分配序號值。 當指定序號值時,序號值的範圍必須是從 1 到 N,其中 N 是 DLL 匯出函式的個數。
例如,包含實現二進位制搜尋樹的程式碼的 DLL 看上去可能像下面這樣:
- LIBRARY BTREE
- EXPORTS
- Insert @1
- Delete @2
- Member @3
- Min @4
如果使用 MFC DLL 嚮導建立 MFC DLL,則嚮導將為您建立主幹 .def 檔案並將其自動新增到專案中。 新增要匯出到此檔案的函式名。 對於非 MFC DLL,必須親自建立 .def 檔案並將其新增到專案中。
如果匯出 C++ 檔案中的函式,必須將修飾名放到 .def 檔案中,或者通過使用外部“C”定義具有標準 C 連結的匯出函式。 如果需要將修飾名放到 .def 檔案中,則可以通過使用 DUMPBIN 工具或 /MAP 連結器選項來獲取修飾名。 請注意,編譯器產生的修飾名是編譯器特定的。 如果將 Visual C++ 編譯器產生的修飾名放到 .def 檔案中,則連結到 DLL 的應用程式必須也是用相同版本的 Visual C++ 生成的,這樣呼叫應用程式中的修飾名才能與 DLL 的 .def 檔案中的匯出名相匹配。
如果生成 擴充套件 DLL 並使用 .def 檔案匯出,則將下列程式碼放在包含匯出類的標頭檔案的開頭和結尾:
- #undef AFX_DATA
- #define AFX_DATA AFX_EXT_DATA
- // <body of your header file>
- #undef AFX_DATA
- #define AFX_DATA
這些程式碼行確保內部使用的 MFC 變數或新增到類的變數是從擴充套件 DLL 匯出(或匯入)的。 例如,當使用 DECLARE_DYNAMIC 派生類時,該巨集擴充套件以將 CRuntimeClass 成員變數新增到類。 省去這四行程式碼可能會導致不能正確編譯或連結 DLL,或在客戶端應用程式連結到 DLL 時導致錯誤。
當生成 DLL 時,連結器使用 .def 檔案建立匯出 (.exp) 檔案和匯入庫 (.lib) 檔案。 然後,連結器使用匯出檔案生成 DLL 檔案。 隱式連結到 DLL 的可執行檔案在生成時連結到匯入庫。
請注意,MFC 本身使用 .def 檔案從 MFCx0.dll 匯出函式和類。
網址:https://msdn.microsoft.com/zh-cn/d91k01sh(v=vs.90)
使用 __declspec(dllexport) 從 DLL 匯出Microsoft 在 Visual C++ 的 16 位編譯器版本中引入了 __export,使編譯器得以自動生成匯出名並將它們放到一個 .lib 檔案中。 然後,此 .lib 檔案就可以像靜態 .lib 那樣用於與 DLL 連結。
在更新的編譯器版本中,可以使用 __declspec(dllexport) 關鍵字從 DLL 匯出資料、函式、類或類成員函式。 __declspec(dllexport) 會將匯出指令新增到物件檔案中,因此您不需要使用 .def 檔案。
當嘗試匯出 C++ 修飾函式名時,這種便利最明顯。 由於對名稱修飾沒有標準規範,因此匯出函式的名稱在不同的編譯器版本中可能有所變化。 如果使用 __declspec(dllexport),僅當解決任何命名約定更改時才必須重新編譯 DLL 和依賴 .exe 檔案。
許多匯出指令(如序號、NONAME 和 PRIVATE)只能在 .def 檔案中建立,並且必須使用 .def 檔案來指定這些特性。 不過,在 .def 檔案的基礎上另外使用 __declspec(dllexport) 不會導致生成錯誤。
若要匯出函式,__declspec(dllexport) 關鍵字必須出現在呼叫約定關鍵字的左邊(如果指定了關鍵字)。 例如:
__declspec(dllexport) void __cdecl Function1(void);
若要匯出類中的所有公共資料成員和成員函式,關鍵字必須出現在類名的左邊,如下所示:
- class __declspec(dllexport) CExampleExport : public CObject
- { ... class definition ... };
說明 |
---|
__declspec(dllexport) 不能應用於具有 __clrcall 呼叫約定的函式。 |
生成 DLL 時,通常建立一個包含正在匯出的函式原型和/或類的標頭檔案,並將 __declspec(dllexport) 新增到標頭檔案中的宣告中。 若要提高程式碼的可讀性,請為 __declspec(dllexport) 定義一個巨集並對正在匯出的每個符號使用該巨集:
#define DllExport __declspec( dllexport )
__declspec(dllexport) 將函式名儲存在 DLL 的匯出表中。
說明 |
---|
將 DLL 原始碼從 Win16 移植到 Win32 時,請用 __declspec(dllexport) 替換 __export 的每個例項。 |
作為參考,請在 Win32 Winbase.h 標頭檔案中搜索。 它包含 __declspec(dllimport) 的用法示例。
網址:https://msdn.microsoft.com/zh-cn/a90k134d(v=vs.90)
模組定義 (.Def) 檔案模組定義 (.def) 檔案為連結器提供有關被連結程式的匯出、特性及其他方面的資訊。 生成 DLL 時,.def 檔案最有用。 由於存在可代替模組定義語句使用的 連結器選項,通常不需要 .def 檔案。
在連結器階段可以使用 /DEF(指定模組定義檔案)連結器選項呼叫 .def 檔案。
如果生成的 .exe 檔案沒有匯出,使用 .def 檔案將使輸出檔案較大並降低載入速度。
有關更多資訊,請參見下列章節:
網址:https://msdn.microsoft.com/zh-cn/28d6s79h(VS.90).aspx