動態鏈結庫程式設計 個人筆記

2021-06-21 07:34:08 字數 3400 閱讀 8086

1. 動態鏈結庫概述 (靜態庫和動態庫、動態鏈結庫的載入)

概述: windows api中的所有函式都包含在dll中.其中有三個最重要的dll:

kernel32.dll,它包含用於管理記憶體、程序和執行緒的各個函式;

uer32.dll,它包含用於執行使用者介面任務(如視窗的建立和訊息的傳送)的各個函式;

gdi32.dll,它包含用於畫圖和顯示文字的各個函式.

2.靜態庫和動態庫

靜態庫:函式和資料被編譯進乙個二進位制檔案(通常擴充套件名為.lib).在使用靜態庫的情況下,在編譯鏈結可執行檔案時,鏈結器從庫中複製這些函式和資料並把它們和應用程式的其他模組組合起來建立最終的可執行檔案(.exe 檔案),發布產品的時候不需要包含靜態庫

動態庫:在使用動態庫的時候,往往提供兩個檔案:乙個引入庫.lib和乙個dll。  引入庫包含被dll 匯出的函式和變數的符號名,dll 包含實際的函式和資料。

3.動態鏈結庫的載入

隱式載入(需要.lib檔案,包含標頭檔案。 同時還需要dll檔案,程式啟動的時候就把動態庫的函式全部載入到記憶體中了)

顯示載入(需要dll檔案,需要時才載入,利用loadlibrary,getprocaddress函式實現)

4.通用動態鏈結庫模板

這種模式的.h檔案,可以適用於匯入函式,也可以適用於匯出函式

在原始檔中包含.h,如果原始檔中定義了dll_api  」_declspec(dllexport)「 那麼在.h中就不定義了,可以用於匯出函式的宣告,而如果在呼叫dll的程式中包含這個頭就可以,因為程式中沒有定義dll_api,所以dll_api被定義為 "_declspec(dllimport)" 這時作為匯入函式的宣告了,

dll.h檔案內容

#ifdef dll_api

#else

#define dll_api _declspec(dllimport)

#endif

dll_api int add(int x,int y);

dll_api int subtract(int x,int y);

cpp檔案內容

#define dll_api _declspec(dllexport)

#include "dll.h"

int add(int x,int y)

int subtract(int x,int y)

5.檢視動態鏈結庫工具

dumpbin (字元介面工具)

dumpbin –imports ***.exe //檢視匯入函式

dumpbin -exports ***.dll //檢視匯出函式

depends(圖形介面工具)

6.從 dll 中匯出c++類

在乙個動態鏈結庫中不僅可以匯出函式,還可以匯出乙個c++類,**示例如下:

class dll_api point

;如果只想匯出類中的部分函式,則可以將dll_api剪下至該函式前面。如void dll_api output(int x,int y);

如果函式在類中被宣告為private,或protect,是無法匯出使用的

7.解決名字改編問題

c++匯出或匯入動態鏈結庫的函式時會發生名字改編。如果不想發生名字改編。就需要在定義匯出函式時,加上限定符:extern 「c」.注意:雙引號中的c 必須是大寫.

#define dll_api extern "c" _declspec(dllexport)

利用限定符:extern 「c」可以解決c++和c 語言之間相互呼叫時函式命名的問題.但是這種方法有乙個缺陷:不能用於匯出乙個類的成員函式,只能使用者匯出全域性函式這種情況.另外,如果匯出函式的呼叫約定發生了改變,那麼即使使用了限定符,名字一樣會發生改編.

這種情況下,可以通過乙個稱為模組定義檔案(def)的方式來解決名字改編的問題.接下來,新增乙個模組定義檔案"**.def」,並寫入如下**:

library dll** //dll檔案的名稱

exports

addsubtract

其中,library 語句用來指定動態鏈結庫的內部名稱,該名稱與生成的動態鏈結庫的名稱一定要匹配.

exports的作用是表明dll 將要匯出的函式,以及為這些匯出函式指定的符號名.

如果要將匯出的符號名和原始檔中定義的函式名不一樣,則可以按照一下語法指定匯出的函式:

entryname=internalname  //前面代表符號名,後面代表函式名

其中, entryname項是匯出的符號名, internalname項是dll中將要匯出的函式名字

8.顯示載入方式載入dll

使用動態方式載入動態鏈結庫時,需要用到loadlibrary函式.該函式的作用是將指定的可執行模組對映到呼叫程序的位址空間.原型如下:

hmodule loadlibrary( lpctstr lpfilename );

該函式返回型別是hmodule,hmoudule型別和hinstance 型別可以通用.當獲取到動態鏈結庫模組的控制代碼後,接著需要獲取該動態鏈結庫中匯出函式的位址,這可以通過呼叫getprocaddress 函式實現,原型如下:

farporc getprocaddress (hmodule hmodule, lpcstr lpprocname);

下面,就利用dlltest程式動態載入dll2.dll並訪問它提供的匯出函式.**如下:

void cdlltestdlg::onbtnadd()

cstring str;

str.format("5+3=%d",add(5,3));

messagebox(str);

}說明:

這裡的addproc 是乙個函式指標型別,而不是乙個變數.

動態載入dll 時,客戶端程式不再需要包含匯出函式宣告的標頭檔案和引入庫檔案,只需要帶dll檔案即可.

9.dllmain 函式

dll檔案的入口函式:dllmain.該函式是可選的.原型如下:

bool winapi dllmain( hinstance hinstdll,dword fdwreason,lpvoid lpvreserved);

注意:如果提供了dllmain 函式,那麼在此函式中不要進行太複雜的呼叫,因為在載入該動態鏈結庫時,可能還有一些核心動態鏈結庫沒有載入,比如user32.dll和gdi32.dll等,由於我們自己的dll會比較靠前的載入,而某些核心沒被載入的話,就可能呼叫失敗.

當我們的動態鏈結庫不再使用時可以呼叫freelibrary 使動態鏈結庫使用計數減1,當使用計數為零時,系統會收回模組資源.

原型如下:

bool freelibrary( hmodule hmodule);

動態鏈結庫程式設計 個人筆記

1.動態鏈結庫概述 靜態庫和動態庫 動態鏈結庫的載入 概述 windows api中的所有函式都包含在dll中.其中有三個最重要的dll kernel32.dll,它包含用於管理記憶體 程序和執行緒的各個函式 uer32.dll,它包含用於執行使用者介面任務 如視窗的建立和訊息的傳送 的各個函式 g...

DLL(動態鏈結庫)程式設計

dll是現在常見的檔案,它整合了程式的很多功能在裡面。一般情況下,它不能直接被執行,常見的使用方法是用其他的 exe呼叫其執行,以使其內部功能表現出來。還有 ocx檔案也與之類似,也就是人們常說的com 1.簡要 windows api中所有的函式都包含在dll中,其中有3個最重要的dll。1 ke...

Windows 動態鏈結庫程式設計

windows 動態鏈結庫程式設計 1 介紹 windows作業系統是應用最關的作業系統,因此動態鏈結庫也為程式設計師所熟悉,即使對於普通的使用者來說,很多時候也會碰到.dll結尾的檔案,這就是動態鏈結庫檔案。windows下的動態鏈結庫可以通過參考標頭檔案和.lib庫檔案進行編譯,從而使得動態鏈結...