dll文件介紹
比較大(dà)的應用程序都由很多模塊(kuài)組成,這些模塊分(fèn)別完(wán)成相對獨立的功能,它們彼(bǐ)此協作來完成整個軟件係統的工作。可能存在一些(xiē)模塊的功(gōng)能較為通(tōng)用,在構造其它(tā)軟(ruǎn)件係統時仍會被使用。在構造軟件係統時,如果將所有模(mó)塊的源代碼都(dōu)靜態編譯到整個應用程序 EXE 文件中(zhōng),會產(chǎn)生(shēng)一些問(wèn)題:一個缺點是增加了應用程序的大(dà)小,它會占用更(gèng)多(duō)的磁盤空間(jiān),程序(xù)運行時也會消(xiāo)耗較大的內存空間,造成係(xì)統資(zī)源的浪費;另一個缺點(diǎn)是,在編寫大的 EXE 程序時,在每(měi)次修改重建時都必須調整編譯所有源代碼(mǎ),增(zēng)加了(le)編譯(yì)過程的(de)複雜性,也(yě)不利(lì)於階段性(xìng)的單元測試。
Windows 係統平台上提供(gòng)了一種完全不同的較(jiào)有效的編(biān)程和運行環(huán)境,你可以將獨(dú)立的(de)程序模塊創建為較小的(de) DLL (Dynamic Linkable Library) 文件,並可(kě)對它們單獨編譯(yì)和(hé)測(cè)試。在運(yùn)行時(shí),隻有當 EXE 程序確實要調用(yòng)這些 DLL 模塊的情(qíng)況下,係統才(cái)會(huì)將它們(men)裝載到內(nèi)存空(kōng)間中。這(zhè)種方式不僅(jǐn)減少(shǎo)了 EXE 文件的大小和對內存(cún)空(kōng)間的需求,而且(qiě)使這些 DLL 模塊可以同(tóng)時被(bèi)多個應(yīng)用程序使用(yòng)。Windows 自己就將(jiāng)一(yī)些(xiē)主要的係統功能以 DLL 模塊的形(xíng)式實現。
一般來說,DLL 是一種磁盤文(wén)件,以(yǐ).dll、.DRV、.FON、.SYS 和許(xǔ)多(duō)以 .EXE 為擴展名的係(xì)統文件(jiàn)都(dōu)可以是 DLL。它由全局數據、服務函(hán)數和資源組成(chéng),在運行時被係統加載到調用進程(chéng)的虛擬空間中,成為(wéi)調用(yòng)進程的一部分。如果(guǒ)與其它 DLL 之間沒有(yǒu)衝突,該(gāi)文件通(tōng)常映射到進程虛擬空間的同一地址上。DLL 模塊中包含各種導出函數,用於(yú)向外界提供服務。DLL 可以有自己的數(shù)據段,但沒有自己的堆棧,使用(yòng)與調用它的應用程序相同的堆(duī)棧模(mó)式(shì);一個 DLL 在(zài)內存中隻有一個實例(lì);DLL 實現(xiàn)了代碼封裝(zhuāng)性;DLL 的編製與(yǔ)具體的編(biān)程語言及編譯器無關。
在 Win32 環境中,每個進程(chéng)都複製了自己的(de)讀/寫全局變量(liàng)。如果(guǒ)想(xiǎng)要與其它進程共享內存,必(bì)須使用內存映射文(wén)件(jiàn)或者聲明一個共享數(shù)據(jù)段。DLL 模塊需要(yào)的(de)堆棧內(nèi)存都是從(cóng)運行進程的堆棧中分配出來的。Windows 在加載(zǎi) DLL 模塊時將(jiāng)進(jìn)程函數(shù)調(diào)用與 DLL 文件(jiàn)的導出函數相匹(pǐ)配。Windows 操作係統對 DLL 的操作僅僅是把 DLL 映射到需要它的進程的虛(xū)擬地(dì)址空間裏去。DLL 函數中的(de)代碼所創建的(de)任何對象(包括變量)都歸調用它的線(xiàn)程(chéng)或進程所有。
調用(yòng)方式
1、靜態(tài)調用方式:由編譯(yì)係(xì)統完成對 DLL 的加載和應用程序結束時 DLL 卸(xiè)載(zǎi)的(de)編碼(mǎ)(如還有(yǒu)其它程序使用該(gāi) DLL,則 Windows 對 DLL 的應用記(jì)錄減1,直到所有相關程序都結(jié)束對(duì)該 DLL 的使用時才(cái)釋放它,簡單實用,但(dàn)不夠(gòu)靈活(huó),隻能滿足(zú)一般要求。
隱式(shì)的(de)調用:需要(yào)把產生動態(tài)連(lián)接庫(kù)時產生的(de) .LIB 文件加入(rù)到應用程序的工程中,想使用 DLL 中的函數時,隻須說明一(yī)下。隱式調用不需要調用 LoadLibrary() 和 FreeLibrary()。程序員在建立一(yī)個 DLL 文件時,鏈(liàn)接程序會自(zì)動生成一個與之對應的 LIB 導(dǎo)入文(wén)件。該文件包含了(le)每一個(gè) DLL 導出函(hán)數的符號名(míng)和可(kě)選的標識號,但是並不含有實(shí)際的代碼。LIB 文件作為 DLL 的替代文件被編譯到應(yīng)用程序(xù)項目中。
當(dāng)程序員通過靜(jìng)態(tài)鏈接方式編譯生成應用程序時,應用(yòng)程(chéng)序中的調用(yòng)函數與 LIB 文件中導出(chū)符號相匹配,這些(xiē)符(fú)號或標識號進入到生成的(de) EXE 文件中(zhōng)。LIB 文(wén)件(jiàn)中也(yě)包含了對應(yīng)的(de) DL L文件名(但不是完(wán)全的路徑名),鏈接(jiē)程序將其(qí)存儲在 EXE 文件內部。
當(dāng)應用程序運行過(guò)程(chéng)中需要加(jiā)載 DLL 文件時,Windows 根據這些信息發現並加載 DLL,然後通過符(fú)號(hào)名(míng)或標識號實現對 DLL 函數的動態鏈接。所有被應用(yòng)程序調用的 DLL 文件都會在應用程序 EXE 文件加載時被加載在到內存中。可執(zhí)行程序鏈接到一個(gè)包含 DLL 輸出函數信息的輸入(rù)庫文件(.LIB文件)。操作係統在加載使用可執(zhí)行程序時加(jiā)載 DLL。可執行程序(xù)直接通過(guò)函(hán)數名調用 DLL 的輸出函數,調用方法和程序內部其 它的函數是一樣的。
2、動態調用方式:是由編程者(zhě)用 API 函數(shù)加載和卸載 DLL 來達到調用 DLL 的目的,使(shǐ)用上(shàng)較複(fù)雜,但能更加有效地使用內存,是編製大型應用程(chéng)序時的(de)重要方式。
顯式的調用(yòng):是指在(zài)應用程序中(zhōng)用(yòng) LoadLibrary 或 MFC 提供的 AfxLoadLibrary 顯式的將(jiāng)自己所做的動(dòng)態(tài)連(lián)接庫(kù)調(diào)進(jìn)來(lái),動態連(lián)接庫的文(wén)件名即是上麵兩個函(hán)數的參數,再用 GetProcAddress() 獲取(qǔ)想(xiǎng)要引入(rù)的(de)函數。自此,你就可以象使用如同本(běn)應(yīng)用程序自定義的函數一樣來調用此引入函數了。在應用程序退出之(zhī)前,應該用(yòng) FreeLibrary 或 MFC 提(tí)供的(de) AfxFreeLibrary 釋(shì)放動態連接(jiē)庫。直接(jiē)調用 Win32 的 LoadLibary 函(hán)數,並(bìng)指定 DLL 的路徑作(zuò)為參數。LoadLibary 返回(huí) HINSTANCE 參數(shù),應用程序在調用 GetProcAddress 函(hán)數時使用這一(yī)參數。GetProcAddress 函數(shù)將符號名或標識號轉換為 DLL 內(nèi)部(bù)的地址。程序員可以決(jué)定 DLL 文(wén)件何時加載或不加(jiā)載,顯式鏈接在運(yùn)行時決定(dìng)加(jiā)載哪個(gè) DLL 文件。使(shǐ)用(yòng) DLL 的程序在使用之前必須加載(LoadLibrary)加載DLL從而得到一個DLL模塊的句柄(bǐng),然後(hòu)調用 GetProcAddress 函數得到輸出函(hán)數的指針,在退出之前必須卸(xiè)載(zǎi)DLL(FreeLibrary)。
Windows將遵(zūn)循下麵的搜索(suǒ)順(shùn)序來定位(wèi) DLL:
- 包含EXE文件的目錄(lù)
- 進程的當前(qián)工作(zuò)目錄(lù)
- Windows係統目錄(lù)
- Windows目錄
- 列在 Path 環境變量中的一係(xì)列目錄
MFC中的DLL
- Non-MFC DLL:指的是不用 MFC 的類庫結構,直(zhí)接用(yòng) C 語言寫(xiě)的 DLL,其輸出的函數一般(bān)用的是標準 C 接口(kǒu),並能被 非 MFC 或 MFC 編寫的應用程序所調用。
- Regular DLL:和(hé)下述的 Extension DLLs 一(yī)樣,是用 MFC 類庫編寫的。明顯的(de)特點是在源文件(jiàn)裏有(yǒu)一(yī)個繼承 CWinApp 的類。其(qí)又可細(xì)分成靜態連接到 MFC 和動態連接到 MFC 上(shàng)的。
靜態連接到 MFC 的動態連接庫隻被 VC 的專業 版和企業(yè)版所支持。該類 DLL 應用程序裏(lǐ)頭的輸出函(hán)數可以被任意 Win32 程序使用,包括使用 MFC 的(de)應用程序。輸入函數有(yǒu)如下形式(shì):
extern "C" EXPORT YourExportedFunction();
如果沒有 extern "C" 修(xiū)飾,輸出函數僅僅能從 C++ 代碼中調用。
DLL 應用程序從 CWinApp 派生(shēng),但沒有消息循環(huán)。
動態鏈接到 MFC 的 規則 DLL 應用程序裏頭的(de)輸(shū)出(chū)函數可以(yǐ)被任意(yì) Win32 程序使用,包括使用 MFC 的應用(yòng)程(chéng)序。但是,所(suǒ)有從 DLL 輸出(chū)的函數應該以如(rú)下語句開始:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
此語(yǔ)句用來正確地切換 MFC 模(mó)塊狀態(tài)。
Regular DLL能夠被所(suǒ)有支(zhī)持 DLL 技(jì)術的語言所編寫的應用程(chéng)序所調(diào)用(yòng)。在這種(zhǒng)動態連接庫中,它必須有(yǒu)一個從(cóng) CWinApp 繼承(chéng)下來(lái)的類,DLLMain 函數被 MFC 所提供,不用自己顯(xiǎn)式(shì)的寫(xiě)出來。
-
Extension DLL:用(yòng)來實(shí)現從 MFC 所繼承下來的類的重新利用(yòng),也(yě)就是說,用這種類型的動態連(lián)接庫,可以用來輸出(chū)一個(gè)從 MFC 所(suǒ)繼承下來的類。它輸出的函數僅(jǐn)可以被使用 MFC 且動態鏈接到 MFC 的(de)應用程序使用。可(kě)以從 MFC 繼承你所想要的、更適於你自(zì)己用的(de)類(lèi),並把(bǎ)它提供(gòng)給(gěi)你的(de)應用(yòng)程序。你也可隨意的給你的應(yīng)用程序提供 MFC 或(huò) MFC 繼承(chéng)類(lèi)的對象(xiàng)指針。Extension DLL使用 MFC 的動態連(lián)接(jiē)版本(běn)所創建的,並且(qiě)它隻被(bèi)用(yòng) MFC 類(lèi)庫所編寫的應用程(chéng)序所(suǒ)調用(yòng)。Extension DLLs 和 Regular DLLs 不一樣,它(tā)沒有從 CWinApp 繼承而來的類的對象,所以,你必須為自己 DLLMain 函數添加初始(shǐ)化代碼和結束代碼。
和規則 DLL 相比(bǐ),有(yǒu)以下不同:
1、它沒有從 CWinApp 派生的對象;
2、它必須有一個 DLLMain 函數;
3、DLLMain 調用 AfxInitExtensionModule 函數,必須檢查該函數(shù)的返回值,如果返回0,DLLMmain 也返回 0;
-
4、如(rú)果它希望輸出 CRuntimeClass 類型的對象或(huò)者資源,則需要提供一個初始化函數來創(chuàng)建一(yī)個(gè) CDynLinkLibrary 對象。並(bìng)且(qiě),有必要把初始(shǐ)化(huà)函(hán)數輸出;
5、使用擴展 DLL 的 MFC 應用程(chéng)序必須有一(yī)個(gè)從 CWinApp 派(pài)生的類,而且,一(yī)般在(zài)InitInstance 裏(lǐ)調用擴展 DLL 的(de)初始(shǐ)化函數。
DLL入口函數
1、每一個 DLL 必須有一個入(rù)口點,DLLMain 是一個缺省的入口函數。DLLMain 負責初始化和結束(shù)工作,每當(dāng)一個新的(de)進(jìn)程或者(zhě)該進程的新的線(xiàn)程(chéng)訪問 DLL 時,或者訪問 DLL 的每一個進程(chéng)或者線(xiàn)程不再使用(yòng)DLL或者結束時,都會調用 DLLMain。但是(shì),使用(yòng) TerminateProcess 或 TerminateThread 結束進程或者線程(chéng),不(bú)會調(diào)用 DLLMain。
DLLMain的(de)函數原型:
BOOL APIENTRY DLLMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID
lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
.......
case DLL_THREAD_ATTACH:
.......
case DLL_THREAD_DETACH:
.......
case DLL_PROCESS_DETACH:
.......
return TRUE;
}
}參數:
hMoudle:是動態庫被(bèi)調用時所傳遞來的一個指向自己的句柄(實(shí)際(jì)上,它是(shì)指向_DGROUP段(duàn)的一個選擇符);
ul_reason_for_call:是(shì)一(yī)個說明(míng)動(dòng)態庫被調原因(yīn)的標(biāo)誌。當進(jìn)程或(huò)線程裝入(rù)或卸載動態(tài)連接庫的時
關鍵詞:dll,dll文件
閱讀本文後您(nín)有什麽感想? 已有 人(rén)給出評價!
- 0
- 0
- 0
- 0
- 0
- 0