轉自:http://blog.chinaunix.net/u1/51538/showart_573215.html
模塊定義 (.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) 時有效。
二.MSDN中的名詞解釋
模塊定義 (.def) 文件為鏈接器提供有關被鏈接程序的導出、屬性及其他方面的信息。生成 DLL 時,.def 文件最有用。由于存在可代替模塊定義語句使用的鏈接器選項,通常不需要 .def 文件。也可以將 __declspec(dllexport) 用作指定導出函數的手段。在鏈接器階段可以使用 /DEF(指定模塊定義文件)鏈接器選項調用 .def 文件。
如果生成的 .exe 文件沒有導出,使用 .def 文件將使輸出文件較大并降低加載速度。
通俗解釋:
在VC
++中,生成DLL可以不使用.def文件。只需要在VC++的函數定義前要加__declspec(dllexport)修飾就可以了。但是使用
__declspec(dllexport)和使用.def文件是有區別的。如果DLL是提供給VC++用戶使用的,你只需要把編譯DLL時產生的.
lib提供給用戶,它可以很輕松地調用你的DLL。但是如果你的DLL是供其他程序如VB、delphi,以及.NET
用戶使用的,那么會產生一個小麻煩。因為VC++對于__declspec(dllexport)聲明的函數會進行名稱轉換,如下面的函數:
__declspec(dllexport) int __stdcall IsWinNT()
會轉換為IsWinNT@0,這樣你在VB中必須這樣聲明:
Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long
@的后面的數由于參數類型不同而可能不同。這顯然不太方便。所以如果要想避免這種轉換,就要使用.def文件方式。
EXPORTS后面的數可以不給,系統會自動分配一個數。對于VB、PB、Delphi用戶,通常使用按名稱進行調用的方式,這個數關系不大,但是對于使用.lib鏈接的VC程序來說,不是按名稱進行調用,而是按照這個數進行調用的,所以最好給出。
例子:我們用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
原文地址
http://wanderwarriorhsiao.blog.hexun.com/13081159_d.html