文章相關視訊教程下載地址:http://pan.baidu.com/s/1skKSrSh

4 動態庫的載入及呼叫

動態庫的載入分為靜態載入、動態載入兩種方式。

4.1 靜態載入動態庫

靜態載入動態庫的步驟包括:設定專案附加庫目錄設定專案附加依賴項;移動DLL檔案以及宣告動態庫的匯出函式。

建立基於對話方塊的MFC專案,其專案名為Use_DLL_Test。其介面佈局及控制元件ID如圖4-1所示。其中,IDC_EDIT_ADD1IDC_EDIT_ADD2用來輸入兩個加數;當點選IDC_BUTTON_ADD按鍵後,呼叫Win32_DLL_Test.dll中的匯出函式add(),實現兩個加數和的運算,並將和在IDC_EDIT_RESULT中顯示出來。

 

4-1 Use_DLL_Test介面佈局

4.1.1 設定專案附加庫目錄

要在Use_DLL_Test專案中使用動態庫Win32_DLL_Test.dll中的匯出函式add(),必須指定Use_DLL_Test專案的附加庫目錄。程式在執行時,就會根據指定的附加庫目錄搜尋所需的庫檔案。

VS2015介面中選擇選單欄“專案->Use_DLL_Test屬性”,之後在彈出的“Use_DLL_Test屬性頁”對話方塊的左側欄中選擇“配置屬性->連結器->常規”,之後在右側的“附加庫目錄”欄中,新增在前文建立的動態庫檔案所在的路徑,如圖4-2所示。

 

4-2 設定專案的附加庫目錄

4.1.2 設定專案的附加依賴項

在設定了專案附加庫目錄之後,還需要設定專案的附加依賴項,即動態庫的lib引入庫檔名。可以通過兩種方法對附加依賴項進行設定:一種是通過專案屬性對話方塊設定,另一種是通過#pragma comment預編譯巨集進行設定。

1通過專案屬性對話方塊設定

“Use_DLL_Test屬性頁”對話方塊的左側欄中選擇“配置屬性->連結器->輸入”,在右側的“附加依賴項”中輸入動態庫的lib引入庫檔名Win32_DLL_Test.lib,如圖4-3所示。

 

4-3 設定專案的附加依賴項

2通過#pragma comment預編譯巨集進行設定

在Use_DLL_Test.cpp原始檔的起始位置處,使用#pragma comment預編譯巨集,來設定專案的附加依賴項:

#pragma comment(lib, "Win32_DLL_Test.lib")

4.1.3 移動DLL檔案

接下來要將Win32_DLL_Test.DLL檔案拷貝到Use_DLL_Test專案所在的原始碼路徑下,或者將Win32_DLL_Test.DLL檔案直接匯入到Use_DLL_Test專案中。

DLL檔案匯入到專案中的方法是在VS2015的介面中,選擇左側的“解決方案資源管理器”,之後選擇“資原始檔”,在滑鼠右鍵選單中選擇“新增->現有項”,在“新增現有項”對話方塊中選擇Win32_DLL_Test.DLL。新增完成之後,就可以看到在“資原始檔”中就包含了Win32_DLL_Test.DLL,如圖4-4所示。

 

4-4 DLL新增到專案中

4.1.4 宣告函式

在Use_DLL_Test專案中,使用add()函式之前,要對其進行宣告。可以使用extern或者_declspec進行宣告。

Use_DLL_Test.cpp的起始位置處使用如下程式碼進行宣告:

extern unsigned int add(unsigned int x, unsigned int y);

或者

_declspec(dllimport)unsigned int add(unsigned int x, unsigned int y);

其中,externC++的關鍵字,用於宣告而不是定義。宣告不分配儲存空間,它只是說明變數/函式定義在其它地方。_declspec(dllimport)表示其修飾的函式是動態庫的匯出函式,在其他程式中使用該函式。

4.1.5 呼叫函式

IDC_EDIT_RESULT按鍵的訊息響應函式中新增如下程式碼

unsigned int result = add(x, y);

SetDlgItemInt(IDC_EDIT_RESULT, result);

即可在IDC_EDIT_RESULT控制元件中將和顯示出來。

4.2 動態載入動態庫

DLL靜態載入是由系統完成對DLL的載入和解除安裝,而動態載入是由程式設計者呼叫API函式進行載入和解除安裝,程式設計者可以決定DLL檔案何時載入、載入哪個動態庫以及何時解除安裝。

4.2.1 匯入動態庫

使用LoadLibrary()函式匯入指定的動態庫,程式碼如下所示:

HINSTANCE hinstLib;

hinstLib = LoadLibrary(_T("C:\\Win32_DLL_Test.dll"));

其中,HINSTANCE表示動態庫例項的控制代碼,程序中的每個DLL模組都被全域性唯一的32個位元組的HINSTANCE控制代碼標識。在Win32中,HINSTANCEHMODULE的值是相同的。LoadLibrary()函式的引數即為要匯入的動態庫的絕對路徑。

4.2.2 在動態庫中找到所需函式的地址

函式的地址即為函式的指標。函數指標是指向函式的指標,像其他指標一樣,函式指標也指向某個特定的型別。函式型別由其返回型別以及形參表確定。

要獲取add()函式的地址,首先要根據add()函式的返回值型別和形參表定義一個指標變數:

typedef unsigned int(*lpAddFun)(unsigned int, unsigned int);

以上程式碼定義了一個名為lpAddFun型別的函式指標,該函式的返回值是unsigned int,具有兩個型別為unsigned int的變數。

之後,呼叫GetProcAddress()函式將add()函式的指標儲存到lpAddFunc型別的物件中。

lpAddFun addFunc;

addFunc = (lpAddFun)GetProcAddress(hinstLib, "add");

其中,GetProcAddress()函式的第一個引數表示動態庫的控制代碼,hinstLib即為在“4.2.1 匯入動態庫”中匯入的動態庫的控制代碼;第二個引數表示要查詢的函式名;返回值為函式的地址,即函式的指標。

4.2.3 匯出函式的呼叫

最後,根據add()函式的地址addFunc即可實現對其本身的呼叫。

unsigned int result = addFunc(x, y);

SetDlgItemInt(IDC_EDIT_RESULT, result);

4.3 釋放動態庫

在完成了動態庫匯出函式的呼叫之後,還需要釋放對動態庫的引用。通過ReleaseLibrary()函式實現對動態庫引用的釋放。

ReleaseLibrary(hinstLib);