使用 .DEF 檔從 DLL 匯出
模組定義 (.def) 檔是文字檔,包含一或多個模組陳述式,說明 DLL 的各種屬性 (Attribute)。 如果您不是使用 __declspec(dllexport) 關鍵字來匯出 DLL 的函式,則 DLL 就需要 .def 檔。
最小的 .def 檔必須包含下列模組定義陳述式:
檔案裡的第一個陳述式必須是 LIBRARY 陳述式。 這個陳述式會將 .def 檔識別為屬於某一個 DLL。 LIBRARY 陳述式會接在 DLL 名稱之後。 連結器會將這個名稱置於 DLL 的匯入程式庫。
EXPORTS 陳述式會列出由 DLL 匯出的函式名稱,和選擇性的函式序數值。 您可以在函式名稱之後加入 @ 符號和數字,來為函式指派序數值。 您所指定的序數值必須介於範圍 1 到 N 之間,N 是指由 DLL 匯出的函式數目。 如果您是根據序數來匯出函式,請參閱根據序數而不是名稱從 DLL 匯出函式以及這個主題。
例如,包含可實作二進位搜尋樹狀結構的程式碼之 DLL 看起來可能會像下面這樣:
LIBRARY BTREE
EXPORTS
Insert @1
Delete @2
Member @3
Min @4
如果您使用 MFC DLL 精靈來建立 MFC DLL,則精靈會為您建立基本架構的 .def 檔,並自動將它加入至專案。 將要匯出的函式名稱加入到這個檔案中。 對於非 MFC DLL,您必須自行建立 .def 檔,並且將它加入至專案。
如果您要在 C++ 檔案裡匯出函式,您必須將裝飾名稱 (Decorated Name) 置於 .def 檔,或使用 extern "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 匯出函式和類別。