windows api中所有的函式都包含在dll中,其中有3個最重要的dll。
(1) kernel32.dll
它包含那些用於管理記憶體、程序和執行緒的函式,例如createthread函式;
(2) user32.dll
它包含那些用於執行使用者介面任務(如視窗的建立和訊息的傳送)的函式,例如createwindow函式;
(3) gdi32.dll
它包含那些用於畫圖和顯示文字的函式。
1. 靜態庫和動態庫
(1) 靜態庫
函式和資料被編譯進乙個二進位制檔案(通常擴充套件名為.lib)。在使用靜態庫的情況下,在編譯鏈結可執行檔案時,鏈結器從庫中複製這些函式和資料並把它們和應用程式的其他模組組合起來建立最終的可執行檔案(.exe檔案).當發布產品時,只需要發布這個可執行檔案,並不需要發布被使用的靜態庫。
(2) 動態庫
在使用動態庫的時候,往往提供兩個檔案:乙個引入庫(.lib)檔案和乙個dll(.dll)檔案。雖然引入庫的字尾名也是」lib」,但是動態庫的引入庫檔案和靜態庫檔案有著本質上的區別,對乙個dll來說,其引入庫檔案(.lib)包含該dll匯出的函式和變數的符號名,而.dll檔案包含該dll實際的函式和資料。在使用動態庫的情況下,在編譯鏈結可執行檔案時,只需要鏈結該dll的引入庫檔案,該dll中的函式**和資料並不複製到可執行檔案中,直到可執行程式執行時,才去載入所需的dll,將該dll對映到程序的位址空間外,然後訪問dll中匯出的函式。這時,發布產品時,除了發布可執行檔案以外,同時還要發布該程式將要呼叫的動態鏈結庫。
2. 在匯出庫標頭檔案中的標準寫法:
#ifdef libdaq_exports
#define libdaq_api __declspec(dllexport)
#else
#define libdaq_api __declspec(dllimport)
#endif
將該標頭檔案新增到某客戶**中時,會自動展開。如果客戶**沒有定義libdaq_exports,那麼libdaq_exports會被定義為__declspec(dllimport)表示有libdaq_exports頭的函式都是從該dll中匯入的。
3. 名字改編和」extern 「c」」
c++編譯器在生成dll時,會對匯出的函式進行名字改編,並且不同的編譯器使用的改變規則不一樣,因此改編後的名字會不一樣。這樣,如果利用不同的編譯器分別生成dll和訪問該dll的客戶端**程式的話,後者在訪問該dll的匯出函式時會出現問題。為了實現通用性,需要加上限定符:extern 「c」。
但是利用限定符extern 「c」可以解決c++和c之間相互呼叫時函式命名的問題,但是這種方法有乙個缺陷,就是不能用於匯出乙個類的成員函式,只能用於匯出全域性函式。
4. 顯示載入方式載入dll
hmodule loadlibrary(lpctstr lpfilename);
loadlibrary函式不僅可以載入dll,還可以載入可執行模組(exe)。當載入可執行模組時,主要是為了訪問該模組內的一些資源,例如對話方塊資源、位圖資源或圖示資源等。loadlibrary函式有乙個字串型別(lpctstr)的引數,該引數指定了可執行模組的名稱,既可以是乙個dll檔案,也可以是乙個exe檔案。如果呼叫成功,loadlibrary函式將返回所載入的那個模組的控制代碼。返回型別hmodule和hinstance可以通用。
當載入到動態鏈結庫模組的控制代碼後,接下來就要想辦法獲取該動態鏈結庫中匯出函式的位址,這可以通過呼叫getprocaddress函式來實現。該函式用來獲取dll匯出函式的位址,其原型宣告如下所示:
farproc getprocaddress(hmodule hmodule, lpcstr lpprocname);
引數lpprocname:乙個指向常量的字元指標,指定dll匯出函式的名字或函式的序號。如果是序號,則序號必須在低位位元組中,高位位元組必須是0。
如果呼叫成功,getprocaddress函式將返回指定匯出函式的位址;否則返回null。
例如:hinstance hinst;
hinst = loadlibrary(「dlltest.dll」);
typedef int (*addproc)(int a, int b);
addproc add = (addproc)getprocaddress(hinst, 「add」);
if (!add)
print(「failure」);
else
process next events
freelibrary(hinst);
呼叫語法:
bool freelibrary(hmodule hmodule);
5. 載入dll的兩種方式優缺點:
採用動態載入方式,那麼可以在需要時才載入dll,而隱式鏈結方式實現起來比較簡單,在編寫客戶端**時就可以把鏈結工作做好,在程式中可以隨時呼叫dll匯出的函式。但是如果程式需要訪問十多個dll時,如果都採用隱式鏈結方式載入它們的話,那麼在該程式啟動時,這些dll都需要被載入到記憶體中,並對映到呼叫程序的位址空間,這樣將加大程式的啟動時間。而且一般來說,在程式執行過程中只是在某個條件滿足時才需要訪問某個dll中的某個函式,其它情況下都不需要訪問這些dll中的函式。但是這時所有的dll都已經被載入到記憶體中,資源浪費是比較嚴重的。這個時候就需要採用顯示載入的方式來訪問dll,在需要時才載入所需的dll。也就是說在需要時才被載入到記憶體中,並被對映到呼叫程序的位址控制項中。需要說明的是,隱式鏈結方式訪問dll時,在程式啟動時也是通過loadlibrary函式載入該程序需要的動態鏈結庫的。
6. dllmain函式
如果提供了dllmain函式(該函式是可以選擇存在的),那麼在此函式中不要進行太複雜的呼叫。因為在載入該動態鏈結庫時,可能還有一些核心動態鏈結庫沒有被載入。例如use32.dll或gdi32.dll。我們自己編寫的dll會比較靠前地被載入。
DLL 動態鏈結庫 專題
0.windows api中所有的函式都包含在dll中,其中有3個最重要的dll。1 kernel32.dll 它包含那些用於管理記憶體 程序和執行緒的函式,例如createthread函式 2 user32.dll 它包含那些用於執行使用者介面任務 如視窗的建立和訊息的傳送 的函式,例如creat...
動態鏈結庫DLL
函式和資料被編譯進乙個二進位制檔案 通常擴充套件名為.lib 靜態庫 在使用靜態庫的情況下,在編譯鏈結可執行檔案時,鏈結器從庫中複製這些函式和資料並把它們和應用程式的其它模組組合起來建立最終的可執行檔案 exe檔案 在多個同樣的程式執行時,系統保留了許多重複的 副本,造成記憶體資源浪費。動態庫 使用...
DLL(動態鏈結庫)程式設計
dll是現在常見的檔案,它整合了程式的很多功能在裡面。一般情況下,它不能直接被執行,常見的使用方法是用其他的 exe呼叫其執行,以使其內部功能表現出來。還有 ocx檔案也與之類似,也就是人們常說的com 1.簡要 windows api中所有的函式都包含在dll中,其中有3個最重要的dll。1 ke...