lib(靜態鏈結庫)與dll(動態鏈結庫)採用的都是共享**的方式,當我們引用了lib,那麼lib中的指令會被直接包含在最終生成的exe檔案中,而我們若使用dll,該dll不必被包含在最終dll檔案中,exe檔案執行時可以「動態」地引用和解除安裝這個dll檔案,並且lib中不可包含其他lib和dll,而dll中仍可包含其他的dll和lib。
常用dll檔案:kernel32.dll:是windows中非常重要的32位動態鏈結庫檔案,屬於核心級檔案,它控制著系統的記憶體管理、資料的輸入輸出操作和中斷處理以及程序排程等;user32.dll中的函式主要控制使用者介面;gdi32.dll中的函式則負責圖形方面的操作。
dll優點:
4.現代編譯器的主要工作流程:源程式(source code)->預處理器(preprocessor)->編譯器(compiler)->匯程式設計序(assembler)->目標程式(object)->聯結器(鏈結器,linker)->可執行程式(executables)
與靜態鏈結庫的關係:在我們使用#pragma comment(lib,」****\\debug\\***.lib」)以後,本檔案生成的obj檔案會與libtest.lib一起連線,在vs裡的附加依賴項裡新增lib檔案也是如此。
5.匯出函式的宣告:
6. .def:
這段**演示了怎樣用.def檔案將函式宣告為dll匯出函式(需在工程中新增lib.def檔案)
;lib.def:匯出dll函式
;library語句說明def檔案相應的dll
library dllt
;後面列出要匯出函式的名稱
exports
;可以在def檔案中的匯出函式名後加@n,表示要匯出函式的序號為n(在進行函式呼叫時,這個序號將發揮其作用)
add@1
.def檔案中的注釋由每個逐行開始處的分號(;)指定,且注釋不能與語句共享一行
可以在命令列中通過dumpbin/exports *.dll 命令檢視*.dll檔案的匯出符號
7.dll的呼叫方式:
由「loadlibray-getprocaddress-freelibrary」這樣的系統api提供的「dll載入-dll函式位址獲取-dll釋放」方式被我們成為dll的動態呼叫。
特點:可以完全由開發者決定何時載入和解除安裝dll。
靜態呼叫的進行需要完成兩個步驟:告訴編譯器與dll對應的.lib檔案所在的路徑及檔名(#pragma comment(lib,」***.lib」));宣告匯入函式(__declspec(dllimport)***(***))。
特點:由編譯系統完成對dll的載入和應用程式結束時dll的解除安裝。當呼叫某dll的應用程式結束時,若系統中還有其他程式使用該dll,則windows對dll的引用記錄減1,知道所有使用該dll的程式都結束時才釋放它。靜態呼叫方式簡單實用,但不如動態呼叫方式靈活。
靜態呼叫方式不再使用系統api來載入、解除安裝dll以及獲取dll中匯出函式的位址。這是因為:當我們通過靜態鏈結方式編譯生成應用程式時,應用程式中呼叫的與.lib檔案中匯出符號相匹配的函式符號將進入到生成的exe 檔案中,.lib檔案中所包含的與之對應的dll檔案的檔名也被編譯器儲存在 exe檔案內部。當應用程式執行過程中需要載入dll檔案時,windows將根據這些資訊發現並載入dll,然後通過符號名實現對dll函式的動態鏈結。這樣,exe將能直接通過函式名呼叫dll的函式,就象呼叫程式內部的其他函式一樣。
dll載入方式補充(道理一樣):
隱式載入是程式載入記憶體時載入所需的dll檔案,且該dll隨主程序始終占用記憶體。在編碼時需要使用#pragma comment(lib,」mydll.lib」)獲得所需函式的入口。注意該.lib與靜態鏈結庫的.lib檔案不同,靜態鏈結庫的.lib中包含了所需函式的**,動態鏈結庫的.lib僅指示函式在dll檔案中的入口。
顯示載入是在程式執行過程中載入,不需要該dll時則將其釋放。在需要時使用loadlibrary載入,不需要時使用freelibrary釋放。如果在loadlibrary時該dll已經在記憶體,則只需將其引用計數加1,如果其引用計數減為0則移出記憶體。
8.dllmain函式:
dllmain函式是dll程式的入口函式,這個函式是dll的內部函式,這意味著不能在應用工程中引用dllmain函式。
dllmain函式的框架結構:
bool apientry dllmain( hmodule hmodule, //本模組控制代碼
dword ul_reason_for_call, //呼叫的原因
lpvoid lpreserved //顯式載入與隱式載入
)return true;
}
ul_reason_for_call引數的值表示本次呼叫的原因,可能是下面四種情況中的一種:
·dll_process_attach:
表示動態鏈結庫剛被某個程序載入
,程式可以在這裡做一些初始化工作,並返回true表示初始化成功,返回false表示初始化出錯。當
dll被對映到程序的位址空間時,系統呼叫該
dll的
dllmain
函式,傳遞的fdwreason引數為
dll_process_attach,這種呼叫只會發生在第一次對映時,如果同乙個程序後來為已經對映進來的
dll在此呼叫loadlibrary或loadlibraryex,作業系統只會增加
dll的使用次數。
·dll_process_detach:
表示動態鏈結庫即將被解除安裝
,程式可以在這裡進行一些資源的釋放工作,如釋放記憶體、關閉檔案等。什麼時候
dll
freelibrary解除
dll對映,有幾個loadlibrary,就要有幾個freelibrary。
程序結束而解除
dll對映,如果程序的終結是因為呼叫了terminateprocess,系統就不會使用
dll_process_detach來呼叫
dll的
dllmain
函式,這就意味著
dll在程序結束前沒有機會執行任何清理工作。
注意:當用dll_process_attach呼叫dll的dllmain函式時,如果返回false,說明沒有初始化成功,系統仍會用dll_process_detach呼叫dll的dllmain函式。因此,必須確保清理那些沒有成功初始化的東西。
·dll_thread_attach:表示應用程式建立了乙個新的執行緒,當程序建立乙個執行緒時,系統檢視當前對映到程序位址空間中的所有dll檔案映像,並用值dll_thread__attach呼叫dll的dllmain函式。新建立的執行緒負責執行這次dll的dllmain函式,只有當所有的dll都處理完這一通知後,系統才允許程序開始執行它的執行緒函式。
注意:程序每次建立執行緒,都會用dll_thread__attach來初始化,哪怕是從執行緒中建立執行緒也是一樣。
·dll_thread_detach:表示某個執行緒正常終止,如果執行緒呼叫了exitthread來結束執行緒(執行緒函式返回時,系統也會自動呼叫exitthread),系統檢視當前對映到程序空間中的所有dll檔案映像,並用dll_thread_detach來呼叫dllmain函式,通知所有的dll去執行執行緒級的清理工作。
注意:如果執行緒的結束是因為系統中的乙個執行緒呼叫了terminatethread,系統就不會用值dll_thread_detach來呼叫所有dll的dllmain函式。
9.dll匯出變數:
dll定義的全域性變數可以被呼叫程序訪問;dll也可以訪問呼叫程序的全域性資料。
若要匯出某全域性變數,我們需要往.def檔案的exports後新增 變數名 data ,在應用程式函式中使用 extern type funcname; 這條語句宣告匯入的不是dll中的全域性變數本身,而是其位址,應用程式必須通過強制指標轉換來使用dll中的全域性變數。例如使用時應:*(type*)funcname = *; 千萬不能不經過強制型別轉換就進行賦值,那樣會將這個變數的位址改變。
而如果是使用_declspec(dllimport)來進行匯入的話,使用變數的時候就不需要進行強制型別轉換,這個方式匯入的就是dll中的全域性變數本身而不是其位址了,個人認為這個方式最為方便簡單。
DLL 動態鏈結庫 學習筆記 靜態鏈結庫的使用
暑期學習正式拉開帷幕。昨天看了看imac的使用,感覺不錯,推薦一下。這幾天準備學學dll 主要參考資料,還有個比較好的資料。上午小小寫了寫靜態鏈結庫的使用。資料相當詳細吖,記錄下自己的收穫。1.對鏈結庫的理解 鏈結庫,顧名思義,是為可執行檔案提供的可鏈結的乙個庫檔案。庫檔案中可以提供一些函式資料等 ...
動態鏈結庫 靜態鏈結庫
包含標頭檔案和庫 idir 指定編譯查詢標頭檔案的目錄,常用於查詢第三方的庫的標頭檔案,例 gcc test.c i.inc o test。ldir 指定鏈結時查詢lib的目錄,常用於查詢第三方庫。llibrary 指定額外鏈結的lib庫 巨集定義 dmacro 以字串 1 預設值 定義 macro...
靜態鏈結庫 動態鏈結庫
庫是寫好的現有的,成熟的,可以復用的 現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的 都從零開始,因此庫的存在意義非同尋常。本質上來說庫是一種可執行 的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種 靜態庫 a lib 和動態庫 so dll windows上對應的是.lib dll ...