動態鏈結庫程式設計 DLL 淺見

2021-06-04 23:33:47 字數 3534 閱讀 6163

首先我們明白「dll」程式設計是很重要的:在windows api 中有3個重要的dll

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

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

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

對於「動態鏈結庫」和「靜態鏈結庫」的區別:簡單來說,前者在編譯的時候鏈結的是生成的 dll.lib 「引導庫」檔案,不是.dll 本身。dll.lib 「引導庫」檔案中包含了 .dll中的變數資訊,函式宣告資訊,還有其他的一些資訊、、、在程式執行的時候還需要通過乙個路徑去找.dll庫的所在(一般的尋找順序是:debug ---> 本目錄 --- >system32 --- > system --- > 其他系統目錄--- > dll.lib提供的目錄),然後完成程式的正常執行。同時在dll載入進客戶端程式的時候,又分為兩種行為:第一種是將庫直接寫入 link中,那麼程式執行時就載入了此庫,但是很多情況下是用不了那麼的函式的,所以很佔記憶體,所以第二種就是動態載入dll。 而對於「靜態鏈結庫」來說,在編譯的時候,就將庫內容鏈結到exe中,所以在客戶端程式執行的時候不需要再提供庫了。

下面看看dll程式設計:

1、.dll:主要檔案,包含最多的資訊,函式的實現、、、

2、.exp:包含的是輸出資訊、、、

3、.lib:包含的是輸入資訊、、、

對於函式能夠被客戶端程式呼叫,我們需要注意很多問題:

1、  為了是函式能夠被客戶端呼叫,也可以被自身呼叫,我們需要做一些手腳,呵呵、、、

在 dll.h 中:

#ifdefdll1_api 

// if 已經定義咯  dll1_api

#else 

#define dll1_api _declspec( dllimport ) //注意:dllimport是外部函式被使用的必須條件

#endif

dll1_api int add( int a, int b); 

// 宣告是外部變數( 函式 )

dll1_api int subtract( int a, int b ); 

//宣告是外部變數( 函式 )

在dll.cpp中:

#define dll1_api _declspec( dllexport )

int add( int a, int b) 

return ( b + a );

int subtract( int a, int b )

return ( a - b );

我們可以解釋一下:if 是內部程式呼叫的話,我們知道,由於在cpp中已經定義了

#define dll1_api _declspec( dllexport )

那麼就不需要在定義dll1_api了。但是對於外部程式而言,只要客戶端沒有定義,那麼我們需要定義#define dll1_api_declspec( dllimport ),對於客戶端程式呼叫的條件!

注:對於_declspec( dllimport )和_declspec( dllexport )在上篇已經說過、、、

2、 我們知道,對於c++而言,在連線dll的時候,我們的函式名已經不一定是原生態的名字咯,呵呵,為什麼這麼說呢?因為c++編譯器有乙個「名字改編」機制,是有影響的!不知道的可以看一下:在 dos 下通過 dumpbin可以看到:

dumpbin –exports dll1.dll 可以看輸出( 匯出 )資訊

dumpbin –imports dll1.dll 可以看輸入( 匯入 )資訊

我們可以看到:原本我的程式**中的函式是:

dll1_api int add( int a, int b); 

// 宣告是外部變數( 函式 )

dll1_api int subtract( int a, int b ); 

//宣告是外部變數( 函式 )

class dll1_apipoint 

// 對於匯出類的處理

public:

void output( int x, int y );

我們可以看到不僅僅是函式,甚至連類的名稱都被改變咯!呵呵~對於c++客戶端程式而言,這樣的呼叫是沒有問題的,但是對於其他的呢?例如c客戶端,那顯然是不行的!我們可以想到乙個辦法解決c客戶端的問題:那就是但我們在定義巨集的時候加上:extern 「c」 是可以的:

#define dll1_api extern "c" _declspec( dllexport )

但是這是對於c語言的標準而言的額,對於其他的是不行的,例如對於winwpi的標準 _stdcall還是不行的,自己可以嘗試!

那麼我們怎麼解決呢!

我們就需呀-------à 模組定義檔案(.def)

乙個簡單例項:

library 

dll2 

exports

addsubtract

乙個.def檔案中只有兩個必需的部分:library 和 exports。

第二行:exports也是必須部分,下面每行分別是函式名。

此處只是簡單介紹、、、具體的看 msdn、、、

對於我們這樣的操作,可以嘗試一下,即使是其他的標準,例如:

int _stdcall add( int x, int y) 

// winapi 標準

int _stdcall subtract( int x, int y )

最後匯出的函式名也是 add 和subtract,不信自己嘗試,o(∩_∩)o~

同樣這樣的操作對於「匯出類」也是可以的哦~~~ 

3、  最後看一下動態載入乙個 dll 庫

首先我們需要函式:loadlibrary,其返回值是hinstance

然後還有很重要的一點是:我們需要獲取函式的位址,那麼我們在此處的操作是利用函式指標來處理:typedef int (_stdcall *instanceadd )( int a, int b ); // 此處我們處理add函式

**如下:

hinstance hinst;

hinst = loadlibrary( "dll2.dll"); 

// 動態載入dll

typedef int ( _stdcall *instanceadd )( int a, int b); 

instanceadd add=( instanceadd )getprocaddress( hinst,makeintresource( 1 )); 

// 函式的id可以在 dumpbin中看到

if ( !add) 

// if add 沒有獲取到函式的位址,那麼返回值是0

messagebox("no address");

return;

cstring str;

str.format( "5 + 3 = %d", add( 5, 3 ) ); // 呼叫外部函式( 注意此處是 add,不是 add )

messagebox( str );

freelibrary( hinst); 

// 釋放 dll

這些就是基礎dll程式設計,大俠們見笑咯~~~

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

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

VC 動態鏈結庫 DLL 程式設計

vc 動態鏈結庫 dll 程式設計 一 理解庫 vc 動態鏈結庫 dll 程式設計 二 非mfc dll vc 動態鏈結庫 dll 程式設計 三 mfc規則dll vc 動態鏈結庫 dll 程式設計 四 mfc擴充套件 dll vc 動態鏈結庫 dll 程式設計 五 dll典型例項 動態鏈結庫 dl...

動態鏈結庫DLL

函式和資料被編譯進乙個二進位制檔案 通常擴充套件名為.lib 靜態庫 在使用靜態庫的情況下,在編譯鏈結可執行檔案時,鏈結器從庫中複製這些函式和資料並把它們和應用程式的其它模組組合起來建立最終的可執行檔案 exe檔案 在多個同樣的程式執行時,系統保留了許多重複的 副本,造成記憶體資源浪費。動態庫 使用...