DEF文件的寫法_第1頁
DEF文件的寫法_第2頁
DEF文件的寫法_第3頁
DEF文件的寫法_第4頁
DEF文件的寫法_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、庫文件1.概論 先來闡述一下DLL(Dynamic Linkable Library)的概念,你可以簡單的把DLL看成一種倉庫,它提供給你一些可以直接拿來用的變量、函數(shù)或類。在倉庫的發(fā)展史上經(jīng)歷了“無庫靜態(tài)鏈接庫動態(tài)鏈接庫”的時代。靜態(tài)鏈接庫與動態(tài)鏈接庫都是共享代碼的方式,如果采用靜態(tài)鏈接庫,則無論你愿不愿意,lib中的指令都被直接包含在最終生成的EXE文件中了。但是若使用DLL,該DLL不必被包含在最終EXE文件中,EXE文件執(zhí)行時可以“動態(tài)”地引用和卸載這個與EXE獨立的DLL文件。靜態(tài)鏈接庫和動態(tài)鏈接庫的另外一個區(qū)別在于靜態(tài)鏈接庫中不能再包含其他的動態(tài)鏈接庫或者靜態(tài)庫,而在動態(tài)鏈接庫中還

2、可以再包含其他的動態(tài)或靜態(tài)鏈接庫。對動態(tài)鏈接庫,我們還需建立如下概念:(1)DLL 的編制與具體的編程語言及編譯器無關只要遵循約定的DLL接口規(guī)范和調(diào)用方式,用各種語言編寫的DLL都可以相互調(diào)用。譬如Windows提供的系統(tǒng)DLL(其中包括了Windows的API),在任何開發(fā)環(huán)境中都能被調(diào)用,不在乎其是Visual Basic、Visual C+還是Delphi。(2)動態(tài)鏈接庫隨處可見我們在Windows目錄下的system32文件夾中會看到kernel32.dll、user32.dll和gdi32.dll,windows的大多數(shù)API都包含在這些DLL中。kernel32.dll中的函數(shù)

3、主要處理內(nèi)存管理和進程調(diào)度;user32.dll中的函數(shù)主要控制用戶界面;gdi32.dll中的函數(shù)則負責圖形方面的操作。一般的程序員都用過類似MessageBox的函數(shù),其實它就包含在user32.dll這個動態(tài)鏈接庫中。由此可見DLL對我們來說其實并不陌生。(3)VC動態(tài)鏈接庫的分類Visual C+支持三種DLL,它們分別是Non-MFC DLL(非MFC動態(tài)庫)、MFC Regular DLL(MFC規(guī)則DLL)、MFC Extension DLL(MFC擴展DLL)。非MFC動態(tài)庫不采用MFC類庫結構,其導出函數(shù)為標準的C接口,能被非MFC或MFC編寫的應用程序所調(diào)用;MFC規(guī)則DL

4、L 包含一個繼承自CWinApp的類,但其無消息循環(huán);MFC擴展DLL采用MFC的動態(tài)鏈接版本創(chuàng)建,它只能被用MFC類庫所編寫的應用程序所調(diào)用。2.靜態(tài)鏈接庫對靜態(tài)鏈接庫的講解不是本文的重點,但是在具體講解DLL之前,通過一個靜態(tài)鏈接庫的例子可以快速地幫助我們建立“庫”的概念。 用visual studio 創(chuàng)建動態(tài)庫如圖1,在VC+6.0中new一個名稱為libTest的static library工程(單擊此處下載本工程),并新建lib.h和lib.cpp兩個文件,lib.h和lib.cpp的源代碼如下:/文件:lib.h#ifndef LIB_H#define LIB_Hextern &

5、quot;C" int add(int x,int y);/聲明為C編譯、連接方式的外部函數(shù)#endif/文件:lib.cpp#include "lib.h"int add(int x,int y)return x + y;編譯這個工程就得到了一個.lib文件,這個文件就是一個函數(shù)庫,它提供了add的功能。將頭文件和.lib文件提交給用戶后,用戶就可以直接使用其中的add函數(shù)了。標準Turbo C2.0中的C庫函數(shù)(我們用來的scanf、printf、memcpy、strcpy等)就來自這種靜態(tài)庫。下面來看看怎么使用這個庫,在libTest工程所在的工作區(qū)內(nèi)new

6、一個libCall工程。libCall工程僅包含一個main.cpp文件,它演示了靜態(tài)鏈接庫的調(diào)用方法,其源代碼如下:#include <stdio.h>#include ".lib.h"#pragma comment( lib, ".debuglibTest.lib" ) /指定與靜態(tài)庫一起連接int main(int argc, char* argv)printf( "2 + 3 = %d", add( 2, 3 ) );靜態(tài)鏈接庫的調(diào)用就是這么簡單,或許我們每天都在用,可是我們沒有明白這個概念。代碼中#pragma

7、comment( lib , ".debuglibTest.lib" )的意思是指本文件生成的.obj文件應與libTest.lib一起連接。如果不用#pragma comment指定,則可以直接在VC+中設置,如圖2,依次選擇tools、options、directories、library files菜單或選項,填入庫文件路徑。圖2中加紅圈的部分為我們添加的libTest.lib文件的路徑。 在VC中設置庫文件路徑這個靜態(tài)鏈接庫的例子至少讓我們明白了庫函數(shù)是怎么回事,它們是哪來的。我們現(xiàn)在有下列模糊認識了:(1)庫不是個怪物,編寫庫的程序和編寫一般的程序區(qū)別不大,只是庫

8、不能單獨執(zhí)行;(2)庫提供一些可以給別的程序調(diào)用的東東,別的程序要調(diào)用它必須以某種方式指明它要調(diào)用之。以上從靜態(tài)鏈接庫分析而得到的對庫的懵懂概念可以直接引申到動態(tài)鏈接庫中,動態(tài)鏈接庫與靜態(tài)鏈接庫在編寫和調(diào)用上的不同體現(xiàn)在庫的外部接口定義及調(diào)用方式略有差異。 靜態(tài)庫目前以lib后綴的庫有兩種,一種為靜態(tài)鏈接庫(Static Libary,以下簡稱“靜態(tài)庫”),另一種為動態(tài)連接庫(DLL,以下簡稱“動態(tài)庫”)的導入庫(Import Libary,以下簡稱“導入庫”)。 靜態(tài)庫是一個或者多個obj文件的打包,所以有人干脆把從obj文件生成lib的過程稱為Archive,即合并到一起。比如你鏈接一個靜

9、態(tài)庫,如果其中有錯,它會準確的找到是哪個obj有錯,即靜態(tài)lib只是殼子。 動態(tài)庫一般會有對應的導入庫,方便程序靜態(tài)載入動態(tài)鏈接庫,否則你可能就需要自己LoadLibary調(diào)入DLL文件,然后再手工GetProcAddress獲得對應函數(shù)了。有了導入庫,你只需要鏈接導入庫后按照頭文件函數(shù)接口的聲明調(diào)用函數(shù)就可以了。 導入庫和靜態(tài)庫的區(qū)別導入庫和靜態(tài)庫的區(qū)別很大,他們實質(zhì)是不一樣的東西。靜態(tài)庫本身就包含了實際執(zhí)行代碼、符號表等等,而對于導入庫而言,其實際的執(zhí)行代碼位于動態(tài)庫中,導入庫只包含了地址符號表等,確保程序找到對應函數(shù)的一些基本地址信息。 這也是實際上很多開源代碼發(fā)布的慣用方式: 1. 預

10、編譯的開發(fā)包:包含一些.dll文件和一些.lib文件。其中這里的.lib就是導入庫,而不要錯以為是靜態(tài)庫。但是引入方式和靜態(tài)庫一樣,要在鏈接路徑上添加找到這些.lib的路徑。而.dll則最好放到最后產(chǎn)生的應用程序exe執(zhí)行文件相同的目錄。這樣運行時,就會自動調(diào)入動態(tài)鏈接庫。 2. 用戶自己編譯: 下載的是源代碼,按照readme自己編譯。生成很可能也是.dll + .lib(導入庫)的庫文件 3. 如果你只有dll,并且你知道dll中函數(shù)的函數(shù)原型,那么你可以直接在自己程序中使用LoadLibary調(diào)入DLL文件,然后使用GetProcAddress調(diào)用DLL中的函數(shù)。當DLL被鏈接時,鏈接程

11、序要查找關于輸出變量,函數(shù),或C+類的信息,并自動生成一個lib文件。該lib文件包含一個DLL輸出的符號列表。如果要鏈接引用該DLL的輸出符號的任何可執(zhí)行模塊,該lib文件是必不可少的(使用GetProcAddress除外)。其實導入庫中并不含RVA(每個符號的相對虛擬地址),只是一些符號而已,還有關于這個lib所對應的DLL的名字等。 (這只是我現(xiàn)在的理解)那當應用程序調(diào)用一個DLL的函數(shù)時,是怎么進行的呢?(使用lib的情況下)答案是在進程的主線程開始運行之前,由加載器完成。加載器根據(jù)輸入節(jié)中DLL的名字按照windows的搜索路徑搜索DLL,找到后DLL映射到進程的地址空間,這是DLL

12、中對應于輸入節(jié)中的各個符號的地址就可以確定了,加載器在這個時候?qū)⒌刂分匦绿钊肟蓤?zhí)行模塊的輸入節(jié)中,動態(tài)連接完成。DEF文件的寫法:LIBRARY   BTREE    / 庫名為BTREE,省略庫名即為動態(tài)鏈接庫文件名EXPORTS        / 輸出   Insert   1    / 帶序號的輸出函數(shù)名   Delete   2   Member&#

13、160;  3   Min   4Dynamic-Link Libraries概述Microsoft Windows DLL程序是包函數(shù)和數(shù)據(jù)的模塊。由調(diào)用它的其它模塊(EXE或DLL)動態(tài)加載。加載時,它被映像到調(diào)用模塊的地址空間內(nèi)。DLL可以定義兩類函數(shù):輸出函數(shù)和內(nèi)部函數(shù)。輸出函數(shù)可以被其它模塊調(diào)用??梢远x輸出數(shù)據(jù),但輸出數(shù)據(jù)一般只由它自己的函數(shù)使用。DLL有助于應用程序?qū)崿F(xiàn)模塊化。當多個應用程序使用相同的模塊時,還能減少內(nèi)存占用,原因是每個應用程序會有自己的數(shù)據(jù)復本,DLL的代碼是共享的。動態(tài)鏈接允許模塊只包含裝載時或運行時系統(tǒng)需要的

14、信息,這點與靜態(tài)鏈接不同。靜態(tài)鏈接時系統(tǒng)會為每個調(diào)用模塊拷貝一份相應的函數(shù)代碼。每個被裝載的DLL都由系統(tǒng)設置一個計數(shù)標志。某個線程使用DLL時,系統(tǒng)將這個計數(shù)值加1,線程結束時,計數(shù)值減1。當計數(shù)值減到0時,系統(tǒng)將其從調(diào)用模塊的虛擬空間中卸載。使用DLL需要有如下規(guī)定:1.裝載DLL的線程可以使用該DLL打開的句柄。同樣,調(diào)用模塊的線程打開的其它句柄也可以由DLL使用。2.DLL使用調(diào)用線程的堆棧。3.DLL參考調(diào)用進程的虛擬內(nèi)存定位地址。動態(tài)鏈接形式使用DLL有兩種方法:1.啟動裝載動態(tài)鏈接。模塊直接調(diào)用DLL輸出函數(shù)。調(diào)用模塊事先必須用輸入函數(shù)表連接到DLL及其使用的其它DLL或庫。模塊

15、的輸入函數(shù)表會指導操作系統(tǒng),在應用程序裝載時需要的DLL函數(shù)的信息和定位方式。2.運行裝載動態(tài)鏈接。調(diào)用模塊用LoadLibrary或LoadLibraryEx函數(shù)在運行時刻裝載DLL。調(diào)用模塊用GetProcAddress函數(shù)等到DLL函數(shù)的句柄,用這個句柄調(diào)用其函數(shù)。這種方法不用輸入函數(shù)表。動態(tài)鏈接的優(yōu)點相比靜態(tài)鏈接,動態(tài)鏈接有幾個優(yōu)點:1.多個進程在同一基地址裝載相同DLL,只需要一個共享DLL即可,它在物理地址空間內(nèi)共享。2.DLL內(nèi)的函數(shù)變化,只要其輸入輸入?yún)?shù)、調(diào)用格式?jīng)]有變,應用程序自身不必重新編譯。靜態(tài)鏈接需要重新編譯。3.DLL提供異步支持。比如應用程序裝載DLL時,用DLL

16、支持一個無效設備。4.不同語言編寫的應用程序可以用約定的調(diào)用格式調(diào)用DLL函數(shù)。潛在缺點是應用程序不是相對獨立的。啟動裝載動態(tài)鏈接時,DLL不存在,程序不被裝載。運行裝載時,如果DLL不存在,由程序處理。創(chuàng)建動態(tài)鏈接庫創(chuàng)建DLL需要一個或多個源文件,可能需要輸出函數(shù)用的連接文件。如果是啟動裝載的DLL,還要創(chuàng)建輸入庫。源文件內(nèi)是輸出函數(shù)和內(nèi)部函數(shù),可選的DLL入口函數(shù)。DLL由多線程的應用程序使用,要將DLL連接成thread-safe類型,以支持多線程,也要同步全局數(shù)據(jù)。輸出函數(shù)的定義是需要編譯程序支持的,聲明方式也不相同。使用MS VC+,有兩種定義輸出函數(shù)的方式:源文件中使用_decls

17、pec 定義,或用.DEF文件定義。輸入庫(.LIB)文件包含連接程序需要的DLL輸出函數(shù),系統(tǒng)定位指定的DLL及其輸出函數(shù)。VC+中要指定該DLL的輸入庫文件(.LIB),才能編譯使用該DLL中的函數(shù)。DLL入口函數(shù)每個DLL必須有入口點,并不必須有入口函數(shù),入口點由連接程序指定。應用程序裝載或卸載DLL時系統(tǒng)會調(diào)用入口函數(shù)。一般在這里進行初始化工作。參看DllEntryPoint函數(shù),用戶可以更改這個函數(shù)名,也要參看連接程序文檔。調(diào)用入口程序的事件:1.裝載DLL后。2.卸載DLL之前。3.進程創(chuàng)建了一個新線程。使用DisableThreadLibraryCalls函數(shù)會取消這個動作。4.

18、線程正常結束,不是使用TerminateThread或TerminateProcess函數(shù)。同一時刻只有一個線程允許調(diào)用DLL入口函數(shù)。DLL可以使用TLS(線程局部存貯表)獲得線程信息。定義格式:BOOL WINAPI DllEntryPoint(    HINSTANCE hinstDLL,  / handle to DLL module    DWORD fdwReason,     / reason for calling function   

19、LPVOID lpReserved )  / reserved函數(shù)開頭處,可以獲得系統(tǒng)傳遞的調(diào)用信息:A process loads the DLL (DLL_PROCESS_ATTACH). The current process creates a new thread (DLL_THREAD_ATTACH). A thread exits normally (DLL_THREAD_DETACH). A process unloads the DLL (DLL_PROCESS_DETACH)不定義入口函數(shù),裝載時會產(chǎn)生錯誤。入口函數(shù)操作成功應該返回TRUE。啟動裝載DLL時的搜索路徑1.啟動模塊路徑。2.當前路徑。3.Windows系統(tǒng)路徑。GetSystemDirectory函數(shù)可以返回這個路徑。4.Windows路徑。GetWindowsDirectory函數(shù)返回這個路徑。5.PATH環(huán)境路徑。運行裝載DLL不同路徑的重名DLL不會認為是相同的DLL。 LoadLibrary 或 LoadLibraryEx函數(shù)會調(diào)用DLL入口函數(shù)。 GetModuleHandle 函數(shù)返回DLL句柄。GetProcAddress函數(shù)獲得地址。運行時加載DLL,在DLL出錯時,應用程序仍可運行,但不能再使用該DLL中的函數(shù)。DLL的數(shù)據(jù)DLL缺省的變量使用范圍與

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論