詳解模塊定義(.def)文件

模塊定義(.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
iDATA
當對同一導出使用PRIVATE和DATA時,PRIVATE必須位於DATA的前面。
有三種導出定義的方法,按照建議的使用順序依次爲:
源代碼中的__declspec(dllexport)關鍵字
.def文件中的XPORTS語句
LINK命令中的/EXPORT規範
所有這三種方法可以用在同一個程序中。LINK在生成包含導出的程序時還創建導入庫,除非生成中使用了.exp文件。  
以下是EXPORTS節的示例:

EXPORTS
   DllCanUnloadNow @1 PRIVATEDATA
   DllWindowName = Name DATA
  DllGetClassObject @4 NONAMEPRIVATE
  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_namespecifier
此處,.section_name爲程序圖像中的節名,specifier爲下列一個或多個訪問修飾符:
EXECUTE
READ
SHARED
WRITE
用空格分開修飾符名。例如:
SECTIONS
.rdata READ WRITE
SECTIONS標記definitions節列表的開始位置。每個定義必須在單獨一行上。SECTIONS關鍵字可以在第一個定義所在的同一行或前一行上。.def文件可以包含一個或多個SECTIONS語句。支持SEGMENTS關鍵字作爲SECTIONS的同義詞。

VisualC++的早期版本支持:
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)時有效。

發佈了77 篇原創文章 · 獲贊 5 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章