模塊定義(.def)文件
模塊定義(.def)文件爲鏈接器提供有關被鏈接程序的導出、屬性及其他方面的信息.生成 DLL 時,.def 文件最有用.由於存在可代替模塊定義語句使用的鏈接器選項,通常不需要.def文件.也可以將__declspec(dllexport)用作指定導出函數的手段.
在鏈接器階段可以使用 /DEF(指定模塊定義文件)鏈接器選項調用.def文件.
如果生成的 .exe 文件沒有導出,使用.def文件將使輸出文件較大並降低加載速度.
模塊定義語句的規則
下列語法規則適用於.def文件中的所有語句.其他適用於特定語句的規則與各語句一起加以說明.
語句、屬性關鍵字和用戶指定的標識符區分大小寫.
包含空格或分號(;)的長文件名必須用引號(")引起.
使用一個或多個空格、製表符或換行符,將語句關鍵字同其參數分開和將各語句分開.指定參數的冒號(:)或等號(=)兩旁有零個或多個空格、製表符或換行符.
如果使用 NAME 或 LIBRARY 語句,則這些語句必須位於所有其他語句之前.
在.def文件中,SECTIONS 和 EXPORTS 語句可以出現多次.每個語句都可以採用多個規範,各規範間必須用一個或多個空格、製表符或換行符分開.語句關鍵字必須在第一個規範的前面出現一次,並且可以在每個附加規範的前面重複.
許多語句都具有等效的 LINK 命令行選項.有關其他詳細信息,請參閱相應的 LINK 選項說明.
.def 文件中的註釋由每個註釋行開始處的分號(;)指定.註釋不能與語句共享一行,但可以在多行語句的規範間出現.(SECTIONS 和 EXPORTS 爲多行語句.)
以十進制或十六進制爲基礎指定數值參數.
如果字符串參數與保留字匹配,則必須用雙引號(")將字符串參數引起.
DESCRIPTION "text"
該語句將字符串寫入 .rdata 節.將指定的 text 用單引號或雙引號(' 或 ")引起.若要在字符串中使用引號(單引號或雙引號),請用其他類型的標記括住字符串.
在模塊定義文件中,DESCRIPTION 僅在生成虛擬設備驅動程序(VxD)時有效.
EXETYPE:dynamic | dev386
在模塊定義文件中,EXETYPE 僅在生成虛擬設備驅動程序(VxD)時有效.如果生成虛擬設備驅動程序時在模塊定義文件中沒有指定 EXETYPE,並且如果沒有指定 /EXETYPE 鏈接器選項,則靜態加載(dev386)生效.
EXPORTS
definitions
EXPORTS 語句引入了一個由一個或多個 definitions(導出的函數或數據)組成的節.每個定義必須在單獨一行上.EXPORTS 關鍵字可以在第一個定義所在的同一行上或在前一行上..def 文件可以包含一個或多個 EXPORTS 語句.
導出 definitions 的語法爲:
entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]
entryname 是要導出的函數名或變量名.這是必選項.如果導出的名稱與 DLL 中的名稱不同,則通過 internalname 指定 DLL 中導出的名稱.例如,如果 DLL 導出函數 func1(),要將它用作 func2(),則應指定:
EXPORTS
func2=func1
@ordinal 允許指定是序號而不是函數名將進入 DLL 的導出表.這有助於最小化 DLL 的大小..LIB 文件將包含序號與函數之間的映射,這使您得以像通常在使用 DLL 的項目中那樣使用函數名.
可選的 NONAME 關鍵字允許只按序號導出,並減小結果 DLL 中導出表的大小.但是,如果要在 DLL 上使用 GetProcAddress,則必須知道序號,因爲名稱將無效.
可選的 PRIVATE 關鍵字禁止將 entryname 放到由 LINK 生成的導入庫中.它對同樣是由 LINK 生成的圖像中的導出無效.
可選的 DATA 關鍵字指定導出的是數據,而不是代碼.例如,可以導出數據變量,如下所示:
EXPORTS
i DATA
當對同一導出使用 PRIVATE 和 DATA 時,PRIVATE 必須位於 DATA 的前面.
有三種導出定義的方法,按照建議的使用順序依次爲:
源代碼中的 __declspec(dllexport)關鍵字
.def 文件中的 EXPORTS 語句
LINK 命令中的 /EXPORT 規範
所有這三種方法可以用在同一個程序中.LINK 在生成包含導出的程序時還創建導入庫,除非生成中使用了 .exp 文件.
以下是 EXPORTS 節的示例:
EXPORTS
DllCanUnloadNow @1 PRIVATE DATA
DllWindowName = Name DATA
DllGetClassObject @4 NONAME PRIVATE
DllRegisterServer @7
DllUnregisterServer
注意,使用.def文件從 DLL 中導出變量時,不需要在變量上指定 __declspec(dllexport).但是,在任何使用 DLL 的文件中,仍必須在數據聲明上使用 __declspec(dllimport).
LIBRARY [library][BASE=address]
該語句通知 LINK 創建 DLL.LINK 同時還創建導入庫,除非生成中使用了 .exp 文件.
library 參數指定 DLL 的名稱.也可以使用 /out 鏈接器選項指定 DLL 輸出名.
BASE=address 參數設置操作系統用來加載 DLL 的基址.該參數重寫 0x10000000 的默認 DLL 位置.有關基址的詳細信息,請參閱 /BASE 選項說明.
請記住,在生成 DLL 時使用 /DLL 鏈接器選項.
/HEAP:reserve[,commit]
HEAPSIZE 所展示的功能與 /HEAP 鏈接器選項相同.
NAME [application][BASE=address]
該語句指定主輸出文件的名稱.另一種指定輸出文件名的方法是使用 /out 鏈接器選項,而另一種設置基址的方法是使用 /BASE 鏈接器選項.如果兩種方法都指定了,則 /OUT 重寫 NAME.
如果生成 DLL,NAME 將隻影響 DLL 名.
SECTIONS
definitions
SECTIONS 語句引入了一個由一個或多個 definitions(關於項目輸出文件各節的訪問說明符)組成的節.每個定義必須在單獨一行上.SECTIONS 關鍵字可以在第一個定義所在的同一行或前一行上..def 文件可以包含一個或多個 SECTIONS 語句.
該 SECTIONS 語句爲圖像文件中的一節或多節設置屬性,並可用於重寫每種節類型的默認屬性.
definitions 的格式爲:
.section_name specifier
此處,.section_name 爲程序圖像中的節名,specifier 爲下列一個或多個訪問修飾符:
EXECUTE
READ
SHARED
WRITE
用空格分開修飾符名.例如:
SECTIONS
.rdata READ WRITE
SECTIONS 標記 definitions 節列表的開始位置.每個定義必須在單獨一行上.SECTIONS 關鍵字可以在第一個定義所在的同一行或前一行上. .def 文件可以包含一個或多個 SECTIONS 語句.支持 SEGMENTS 關鍵字作爲 SECTIONS 的同義詞.
Visual C++ 的早期版本支持:
section [CLASS 'classname'] specifier
出於兼容性考慮,支持 CLASS 關鍵字,但忽略了它.
另一種指定節屬性的方法是使用 /SECTION 選項.
STACKSIZE reserve[,commit]
該語句設置堆棧的大小(以字節爲單位).另一種設置堆棧的方法是使用堆棧分配(/STACK)選項.有關 reserve 和 commit 參數的詳細信息,請參閱關於該選項的文檔.
該選項對 DLL 無效.
STUB:filename
當用於生成虛擬設備驅動程序(VxD)的模塊定義文件時,STUB 允許指定包含將在 VxD 中使用的 IMAGE_DOS_HEADER 結構(在 WINNT.H 中定義)而不是默認頭的文件名.
另一種指定 filename 的方法是使用 /STUB 鏈接器選項.
在模塊定義文件中,STUB 僅在生成虛擬設備驅動程序(VxD)時有效.
VERSION major[.minor]
該語句通知 LINK 將一個數字放到 .exe 文件或 DLL 的頭中.major 和 minor 參數是從 0 到 65,535 的範圍內的十進制數.默認值爲 0.0 版.
另一種指定版本號的方法是使用版本信息(/VERSION)選項.
VXD filename
允許指定虛擬設備驅動程序(VxD)的名稱.默認情況下,VxD 獲取與第一個對象文件相同的名稱.
另一種指定虛擬設備驅動程序版本的方法是使用 /VXD 鏈接器選項,另一種命名輸出文件的方法是使用 /out 選項.
在模塊定義文件中,VXD 僅在生成虛擬設備驅動程序(VxD)時有效.