標籤:style 使用 strong 檔案 資料 width
DLL是一個包含函數和資料的模組, 它們可以被其他模組(應用程式或DLL)使用。
DLL可以定義兩種函數: <1>匯出函數 <2>內建函式 .
匯出函數可以被內部或其他模組調用。
內建函式只能在DLL內部被調用。
- About Dynamic-Link Libraries
動態串連 允許一個模組在載入或運行時,僅僅只需包含定位一個動態庫匯出函數的資訊,而無需將這個動態庫整個編譯進模組中。
調用一個DLL中的函數,有兩種方法:
<1> load-time dynamic linking.(載入時動態連結), 是指顯示地調用動態庫中匯出函數,就像這些函數在本地一樣。 這需要你將模組與DLL對應的匯入庫檔案進行連結。
<2> run-time dynamic linking(運行時動態連結), 在運行時使用LoadLibrary或者LoadLibraryEx函數來載入動態庫。 當模組被載入後,使用GetProcAddress函數來擷取動態庫中匯出的函數的地址。
DLL和記憶體管理:
每個進程將DLL載入到它的虛擬位址空間, 當DLL被載入到進程的虛擬位址空間後,他就可以調用DLL的匯出函數了。
系統為每個引用的DLL維護一個引用計數,當一個線程載入DLL,引用計數會加1,當進程結束,引用計數減1,, 當引用計數為0時,DLL會被從虛擬位址空間中卸載。
與其他函數一樣,一個匯出的DLL函數運行在調用它的線程的上下文中,所以:
<1>進程中調用DLL的線程可以使用 被DLL函數開啟的控制代碼,相似地,由線程開啟的控制代碼也可以被DLL函數使用。
<2>DLL使用調用它的線程的棧, 使用調用它的進程的虛擬位址空間。
<3>DLL從調用它的進程的虛擬位址空間中分配記憶體。
動態連結程式庫的優點:(相對於靜態連結庫)
<1>節省記憶體。 當多個進程載入相同的DLL時,DLL只會在實體記憶體中載入一份DLL, 每個進程載入DLL在實體記憶體中同一個基地址。
<2>當DLL的函數的實現改變,而函式宣告沒變的情況下,從新產生DLL。應用程式不需要重新編譯和連結。
<3>不同程式設計語言寫的程式可以調用相同的DLL函數,只要遵循呼叫慣例。
呼叫慣例(如C , Pascal , 或者標準調用) 控制調用函數參數的壓棧順序,是否調用函數,還是被調用函數負責清理棧,是否任何參數被傳遞到寄存器中等。
使用動態庫的潛在的缺點是: 引用程式不是自包含的: DLL依賴於DLL的存在。
當使用load-time dynamic linking, 如果應用程式需要的DLL不存在,那麼系統將結束這個進程。
當使用run-time dynamic linking, 如果需要的DLL不存在,系統不會結束該進程,但是DLL匯出還是不可用。
建立動態連結程式庫
安全執行緒: 如果你的DLL被多線程應用程式使用,那必須對所有DLL資料進行同步,以避免資料汙染。
如果要使用load-time dynamic linking, 必須建立一個匯入庫(.lib檔案).
匯出函數的兩個方法:
<1>使用 __declspec 修飾符
<2>使用.def檔案
建立匯入庫: .lib檔案。 如何建立匯入庫?
動態連結程式庫的進入點函數
動態庫可以可選地指定一個進入點函數。 如果指定了,當一個進程或線程載入或卸載動態庫時,系統都會執行進入點函數。 它可以被用來執行一些初始化和清理任務。
DllMain是一個預留位置,當建立自己的DLL時,必須指定實際的進入點函數名字。
入口函數定義:DLL進入點函數必須以標準呼叫慣例(standard-call calling convention)定義
DLL的匯入庫(即與dll檔案相對應的.lib檔案),提供系統載入動態庫所需要的資訊;並且提供定位動態庫中的匯出函數資訊。