def文件格式
2011年03月18日 模塊定義 (.def) 文件 模塊定義 (.def) 文件為鏈接器提供有關(guān)被鏈接程序的導出、屬性及其他方面的 信息。生成 DLL 時,.def 文件最有用。由于存在可代替模塊定義語句使用的鏈接器選項,通常不需要 .def 文件。也可以將__declspec(dllexport) 用作指定導出函數(shù)的手段。 在鏈接器階段可以使用 /DEF(指定模塊定義文件)鏈接器選項調(diào)用 .def 文件。 如果生成的 .exe 文件沒有導出,使用 .def 文件將使輸出文件較大并降低加載速度。 模塊定義語句的規(guī)則 下列語法規(guī)則適用于 .def 文件中的所有語句。其他適用于特定語句的規(guī)則與各語句一起加以說明。 語句、屬性關(guān)鍵字和用戶指定的標識符區(qū)分大小寫。 包含空格或分號 (;) 的長文件名必須用引號 (") 引起。 使用一個或多個空格、制表符或換行符,將語句關(guān)鍵字同其參數(shù)分開和將各語句分開。指定參數(shù)的冒號 (:) 或等號 (=) 兩旁有零個或多個空格、制表符或換行符。 如果使用 NAME 或 LIBRARY 語句,則這些語句必須位于所有其他語句之前。 在 .def 文件中,SECTIONS 和 EXPORTS 語句可以出現(xiàn)多次。每個語句都可以采用多個規(guī)范,各規(guī)范間必須用一個或多個空格、制表符或換行符分開。語句關(guān)鍵字必須在第一個規(guī)范的前面出現(xiàn)一次,并且可以在每個附加規(guī)范的前面重復。 許多語句都具有等效的 LINK 命令行選項。有關(guān)其他詳細信息,請參閱相應的 LINK 選項說明。 .def 文件中的注釋由每個注釋行開始處的分號 (;) 指定。注釋不能與語句共享一行,但可以在多行語句的規(guī)范間出現(xiàn)。(SECTIONS 和 EXPORTS 為多行語句。) 以十進制或十六進制為基礎(chǔ)指定數(shù)值參數(shù)。 如果字符串參數(shù)與保留字匹配,則必須用雙引號 (") 將字符串參數(shù)引起。 DESCRIPTION "text" 該語句將字符串寫入 .rdata 節(jié)。將指定的 text 用單引號或雙引號(' 或 ")引起。若要在字符串中使用引號(單引號或雙引號),請用其他類型的標記括住字符串。 在模塊定義文件中,DESCRIPTION 僅在生成虛擬設(shè)備驅(qū)動程序 (VxD) 時有效。 EXETYPE:dynamic | dev386 在模塊定義文件中,EXETYPE 僅在生成虛擬設(shè)備驅(qū)動程序 (VxD) 時有效。如果生成虛擬設(shè)備驅(qū)動程序時在模塊定義文件中沒有指定 EXETYPE,并且如果沒有指定 /EXETYPE 鏈接器選項,則靜態(tài)加載 (dev386) 生效。 EXPORTS definitions EXPORTS 語句引入了一個由一個或多個 definitions(導出的函數(shù)或數(shù)據(jù))組成的節(jié)。每個定義必須在單獨一行上。EXPORTS 關(guān)鍵字可以在第一個定義所在的同一行上或在前一行上。.def 文件可以包含一個或多個 EXPORTS 語句。 導出 definitions 的語法為: entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA] entryname 是要導出的函數(shù)名或變量名。這是必選項。如果導出的名稱與 DLL 中的名稱不同,則通過 internalname 指定 DLL 中導出的名稱。例如,如果 DLL 導出函數(shù) func1(),要將它用作 func2(),則應指定: EXPORTS func2=func1 @ordinal 允許指定是序號而不是函數(shù)名將進入 DLL 的導出表。這有助于最小化 DLL 的大小。.LIB 文件將包含序號與函數(shù)之間的映射,這使您得以像通常在使用 DLL 的項目中那樣使用函數(shù)名。 可選的 NONAME 關(guān)鍵字允許只按序號導出,并減小結(jié)果 DLL 中導出表的大小。但是,如果要在 DLL 上使用 GetProcAddress,則必須知道序號,因為名稱將無效。 可選的 PRIVATE 關(guān)鍵字禁止將 entryname 放到由 LINK 生成的導入庫中。它對同樣是由 LINK 生成的圖像中的導出無效。 可選的 DATA 關(guān)鍵字指定導出的是數(shù)據(jù),而不是代碼。例如,可以導出數(shù)據(jù)變量,如下所示: EXPORTS i DATA 當對同一導出使用 PRIVATE 和 DATA 時,PRIVATE 必須位于 DATA 的前面。 有三種導出定義的方法,按照建議的使用順序依次為: 源代碼中的 __declspec(dllexport) 關(guān)鍵字 .def 文件中的 EXPORTS 語句 LINK 命令中的 /EXPORT 規(guī)范 所有這三種方法可以用在同一個程序中。LINK 在生成包含導出的程序時還創(chuàng)建導入庫,除非生成中使用了 .exp 文件。 以下是 EXPORTS 節(jié)的示例: EXPORTS DllCanUnloadNow @1 PRIVATE DATA DllWindowName = Name DATA DllGetClassObject @4 NONAME PRIVATE DllRegisterServer @7 DllUnregisterServer 注意,使用 .def 文件從 DLL 中導出變量時,不需要在變量上指定 __declspec(dllexport)。但是,在任何使用 DLL 的文件中,仍必須在數(shù)據(jù)聲明上使用 __declspec(dllimport)。 LIBRARY [library][BASE=address] 該語句通知 LINK 創(chuàng)建 DLL。LINK 同時還創(chuàng)建導入庫,除非生成中使用了 .exp 文件。 library 參數(shù)指定 DLL 的名稱。也可以使用 /out 鏈接器選項指定 DLL 輸出名。 BASE=address 參數(shù)設(shè)置操作系統(tǒng)用來加載 DLL 的基址。該參數(shù)重寫 0x10000000 的默認 DLL 位置。有關(guān)基址的詳細信息,請參閱 /BASE 選項說明。 請記住,在生成 DLL 時使用 /DLL 鏈接器選項。 /HEAP:reserve[,commit] HEAPSIZE 所展示的功能與 /HEAP 鏈接器選項相同。 NAME [application][BASE=address] 該語句指定主輸出文件的名稱。另一種指定輸出文件名的方法是使用 /out 鏈接器選項,而另一種設(shè)置基址的方法是使用 /BASE 鏈接器選項。如果兩種方法都指定了,則 /OUT 重寫 NAME。 如果生成 DLL,NAME 將只影響 DLL 名。 SECTIONS definitions SECTIONS 語句引入了一個由一個或多個 definitions(關(guān)于項目輸出文件各節(jié)的訪問說明符)組成的節(jié)。每個定義必須在單獨一行上。SECTIONS 關(guān)鍵字可以在第一個定義所在的同一行或前一行上。.def 文件可以包含一個或多個 SECTIONS 語句。 該 SECTIONS 語句為圖像文件中的一節(jié)或多節(jié)設(shè)置屬性,并可用于重寫每種節(jié)類型的默認屬性。 definitions 的格式為: .section_name specifier 此處,.section_name 為程序圖像中的節(jié)名,specifier 為下列一個或多個訪問修飾符: EXECUTE READ SHARED WRITE 用空格分開修飾符名。例如: SECTIONS .rdata READ WRITE SECTIONS 標記 definitions 節(jié)列表的開始位置。每個定義必須在單獨一行上。SECTIONS 關(guān)鍵字可以在第一個定義所在的同一行或前一行上。.def 文件可以包含一個或多個 SECTIONS 語句。支持 SEGMENTS 關(guān)鍵字作為 SECTIONS 的同義詞。 Visual C++ 的早期版本支持: section [CLASS 'classname'] specifier 出于兼容性考慮,支持 CLASS 關(guān)鍵字,但忽略了它。 另一種指定節(jié)屬性的方法是使用 /SECTION 選項。 STACKSIZE reserve[,commit] 該語句設(shè)置堆棧的大?。ㄒ宰止?jié)為單位)。另一種設(shè)置堆棧的方法是使用堆棧分配 (/STACK) 選項。有關(guān) reserve 和 commit 參數(shù)的詳細信息,請參閱關(guān)于該選項的文檔。 該選項對 DLL 無效。 STUB:filename 當用于生成虛擬設(shè)備驅(qū)動程序 (VxD) 的模塊定義文件時,STUB 允許指定包含將在 VxD 中使用的 IMAGE_DOS_HEADER 結(jié)構(gòu)(在 WINNT.H 中定義)而不是默認頭的文件名。 另一種指定 filename 的方法是使用 /STUB 鏈接器選項。 在模塊定義文件中,STUB 僅在生成虛擬設(shè)備驅(qū)動程序 (VxD) 時有效。 VERSION major[.minor] 該語句通知 LINK 將一個數(shù)字放到 .exe 文件或 DLL 的頭中。major 和 minor 參數(shù)是從 0 到 65,535 的范圍內(nèi)的十進制數(shù)。默認值為 0.0 版。 另一種指定版本號的方法是使用版本信息 (/VERSION) 選項。 VXD filename 允許指定虛擬設(shè)備驅(qū)動程序 (VxD) 的名稱。默認情況下,VxD 獲取與第一個對象文件相同的名稱。 另一種指定虛擬設(shè)備驅(qū)動程序版本的方法是使用 /VXD 鏈接器選項,另一種命名輸出文件的方法是使用 /out 選項。 在模塊定義文件中,VXD 僅在生成虛擬設(shè)備驅(qū)動程序 (VxD) 時有效。 二.MSDN中的名詞解釋 模塊定義 (.def) 文件為鏈接器提供有關(guān)被鏈接程序的導出、屬性及其他方面的信息。生成 DLL 時,.def 文件最有用。由于存在可代替模塊定義語句使用的鏈接器選項,通常不需要 .def 文件。也可以將 __declspec(dllexport) 用作指定導出函數(shù)的手段。在鏈接器階段可以使用 /DEF(指定模塊定義文件)鏈接器選項調(diào)用 .def 文件。 如果生成的 .exe 文件沒有導出,使用 .def 文件將使輸出文件較大并降低加載速度。 通俗解釋: 在VC ++中,生成DLL可以不使用.def文件。只需要在VC++的函數(shù)定義前要加__declspec(dllexport)修飾就可以了。但是使用 __declspec(dllexport)和使用.def文件是有區(qū)別的。如果DLL是提供給VC++用戶使用的,你只需要把編譯DLL時產(chǎn)生的. lib提供給用戶,它可以很輕松地調(diào)用你的DLL。但是如果你的DLL是供其他程序如VB、delphi,以及.NET 用戶使用的,那么會產(chǎn)生一個小麻煩。因為VC++對于__declspec(dllexport)聲明的函數(shù)會進行名稱轉(zhuǎn)換,如下面的函數(shù): __declspec(dllexport) int __stdcall IsWinNT() 會轉(zhuǎn)換為IsWinNT@0,這樣你在VB中必須這樣聲明: Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long @的后面的數(shù)由于參數(shù)類型不同而可能不同。這顯然不太方便。所以如果要想避免這種轉(zhuǎn)換,就要使用.def文件方式。 EXPORTS后面的數(shù)可以不給,系統(tǒng)會自動分配一個數(shù)。對于VB、PB、Delphi用戶,通常使用按名稱進行調(diào)用的方式,這個數(shù)關(guān)系不大,但是對于使用.lib鏈接的VC程序來說,不是按名稱進行調(diào)用,而是按照這個數(shù)進行調(diào)用的,所以最好給出。 例子:我們用VC6.0制作一個dll,不使用.def文件,在頭文件中這樣寫 #ifndef LIB_H #define LIB_H extern "C" int _declspec(dllexport)add(int x,int y); #endif 如果是.def文件,可以這樣 LIBRARY "xxx_dll" EXPORTS add PRIVAT |
|