比較大的應用程式都由很多模組組成,這些模組分別完成相對獨立的功能,它們彼此協作來完成整個軟體系統的工作。可能存在一些模組的功能較為通用,在構造其它軟體系統時仍會被使用。在構造軟體系統時,如果將所有模組的原始碼都靜態編譯到整個應用程式 EXE 檔案中,會產生一些問題:一個缺點是增加了應用程式的大小,它會佔用更多的磁碟空間,程式運行時也會消耗較大的記憶體空間,造成系統資源的浪費;另一個缺點是,在編寫大的 EXE 程式時,在每次修改重建時都必須調整編譯所有原始碼,增加了編譯過程的複雜性,也不利於階段性的單元測試。
Windows 系統平台上提供了一種完全不同的較有效編程和運行環境,你可以將獨立的程式模組建立為較小的 DLL 檔案,並可對它們單獨編譯和測試。在運行時,只有當 EXE 程式確實要調用這些 DLL 模組的情況下,系統才會將它們裝載到記憶體空間中。這種方式不僅減少了 EXE 檔案的大小和對記憶體空間的需求,而且使這些 DLL 模組可以同時被多個應用程式使用。Windows 自己就將一些主要的系統功能以 DLL 模組的形式實現。
一般來說,DLL 是一種磁碟檔案,以.dll、.DRV、.FON、.SYS 和許多以 .EXE 為副檔名的系統檔案都可以是 DLL。它由全域資料、服務函數和資源群組成,在運行時被系統載入到調用進程的虛擬空間中,成為調用進程的一部分。如果與其它 DLL 之間沒有衝突,該檔案通常映射到進程虛擬空間的同一地址上。DLL 模組中包含各種匯出函數,用於向外界提供服務。DLL 可以有自己的資料區段,但沒有自己的堆棧,使用與調用它的應用程式相同的堆棧模式;一個 DLL 在記憶體中只有一個執行個體;DLL 實現了代碼封裝性;DLL 的編製與具體的程式設計語言及編譯器無關。
在 Win32 環境中,每個進程都複製了自己的讀/寫全域變數。如果想要與其它進程共用記憶體,必須使用記憶體對應檔或者聲明一個共用資料區段。DLL 模組需要的堆棧記憶體都是從運行進程的堆棧中分配出來的。Windows 在載入 DLL 模組時將進程函數調用與 DLL 檔案的匯出函數相匹配。Windows 作業系統對 DLL 的操作僅僅是把 DLL 映射到需要它的進程的虛擬位址空間裡去。DLL 函數中的代碼所建立的任何對象(包括變數)都歸調用它的線程或進程所有。
調用方式:
1、靜態調用方式:由編譯系統完成對 DLL 的載入和應用程式結束時 DLL 卸載的編碼(如還有其它程式使用該 DLL,則 Windows 對 DLL 的應用記錄減1,直到所有相關程式都結束對該 DLL 的使用時才釋放它,簡單實用,但不夠靈活,只能滿足一般要求。
隱式的調用:需要把產生動態串連庫時產生的 .LIB 檔案加入到應用程式的工程中,想使用 DLL 中的函數時,只須說明一下。隱式調用不需要調用 LoadLibrary() 和 FreeLibrary()。程式員在建立一個 DLL 檔案時,連結程式會自動產生一個與之對應的 LIB 匯入檔案。該檔案包含了每一個 DLL 匯出函數的符號名和可選的標識號,但是並不含有實際的代碼。LIB 檔案作為 DLL 的替代檔案被編譯到應用程式項目中。
當程式員通過靜態連結方式編譯產生應用程式時,應用程式中的調用函數與 LIB 檔案中匯出符號相匹配,這些符號或標識號進入到產生的 EXE 檔案中。LIB 檔案中也包含了對應的 DL L檔案名稱(但不是完全的路徑名),連結程式將其儲存在 EXE 檔案內部。
當應用程式運行過程中需要載入 DLL 檔案時,Windows 根據這些資訊發現並載入 DLL,然後通過符號名或標識號實現對 DLL 函數的動態連結。所有被應用程式調用的 DLL 檔案都會在應用程式 EXE 檔案載入時被載入在到記憶體中。可執行程式連結到一個包含 DLL 輸出函數資訊的輸入庫檔案(.LIB檔案)。作業系統在載入使用可執行程式時載入 DLL。可執行程式直接通過函數名調用 DLL 的輸出函數,調用方法和程式內部其 它的函數是一樣的。
2、動態調用方式:是由編程者用 API 函數載入和卸載 DLL 來達到調用 DLL 的目的,使用上較複雜,但能更加有效地使用記憶體,是編製大型應用程式時的重要方式。
顯式的調用:
是指在應用程式中用 LoadLibrary 或 MFC 提供的 AfxLoadLibrary 顯式的將自己所做的動態串連庫調進來,動態串連庫的檔案名稱即是上面兩個函數的參數,再用 GetProcAddress() 擷取想要引入的函數。自此,你就可以象使用如同本應用程式自訂的函數一樣來調用此引入函數了。在應用程式退出之前,應該用 FreeLibrary 或 MFC 提供的 AfxFreeLibrary 釋放動態串連庫。直接調用 Win32 的 LoadLibary 函數,並指定 DLL 的路徑作為參數。LoadLibary 返回 HINSTANCE 參數,應用程式在調用 GetProcAddress 函數時使用這一參數。GetProcAddress 函數將符號名或標識號轉換為 DLL 內部的地址。程式員可以決定 DLL 檔案何時載入或不載入,顯式連結在運行時決定載入哪個 DLL 檔案。使用 DLL 的程式在使用之前必須載入(LoadLibrary)載入DLL從而得到一個DLL模組的控制代碼,然後調用 GetProcAddress 函數得到輸出函數的指標,在退出之前必須卸載DLL(FreeLibrary)。
正因為DLL 有佔用記憶體小,好編輯等的特點有很多電腦病毒都是DLL格式檔案。但不能單獨運行。
動態連結程式庫通常都不能直接運行,也不能接收訊息。它們是一些獨立的檔案,其中包含能被可執行程式或其它DLL調用來完成某項工作的函數。只有在其它模組調用動態連結程式庫中的函數時,它才發揮作用。