首先介紹:用#import匯入dll和用#pragma comment匯入lib還有在程式中LoadLibrary載入dll有什麼區別
(1)、#import 匯入的dll是com組建的dll,主要用來解析com組建內部結構,便與c++識別調用,
(2)、#pragma comment 是靜態載入庫
(3)、 LoadLibrary 動態載入動態庫
Windows提供了兩種將DLL映像到進程地址空間的方法:
調用DLL,首先需要將DLL檔案映像到使用者進程的地址空間中,然後才能進行函數調用,這個函數和進程內部一般函數的調用方法相同。
1.
隱式的載入時連結
這種方法需要DLL工程經編譯產生的LIB檔案,此檔案中包含了DLL允許應用程式調用的所有函數的列表,當連結器發現應用程式調用了LIB檔案列出的某個函數,就會在應用程式的可執行檔的檔案映像中加入一些資訊,這些資訊指出了包含這個函數的DLL檔案的名字。當這個應用程式運行時,也就是它的可執行檔被作業系統產生映像檔案時,系統會查看這個映像檔案中關於DLL的資訊,然後將這個DLL檔案映像到進程的地址空間。
系統通過DLL檔案的名稱,試圖載入這個檔案到進程地址空間時,它尋找DLL
檔案的路徑按照先後順序如下:
·程式運行時的目錄,即可執行檔所在的目錄;
·當前程式工作目錄
·系統目錄:對於Windows95/98來說,可以調用GetSystemDirectory函數來得到,對於WindowsNT/2000
來說,指的是32位Windows的系統目錄,也可以調用GetSystemDirectory函數來得到,得到的值為SYSTEM32。
·Windows目錄
·列在PATH環境變數中的所有目錄
VC中載入DLL的LIB檔案的方法有以下三種:
①LIB檔案直接加入到工程檔案清單中
在VC中開啟File View一頁,選中工程名,單擊滑鼠右鍵,然後選中“Add Files to Project”菜單,在彈出的檔案對話方塊中選中要加入DLL的LIB檔案即可。
②設定工程的 Project Settings來載入DLL的LIB檔案
開啟工程的 Project Settings菜單,選中Link,然後在Object/library modules下的文字框中輸入DLL的LIB檔案。
③通過程式碼的方式
加入先行編譯指令#pragma comment (lib,”*.lib”),這種方法優點是可以利用條件先行編譯指令連結不同版本的LIB檔案。因為,在Debug方式下,產生的LIB檔案是Debug
版本,如Regd.lib;在Release方式下,產生的LIB檔案是Release版本,如Regr.lib。
當應用程式對DLL的LIB檔案載入後,還需要把DLL對應的標頭檔(*.h)包含到其中,在這個標頭檔中給出了DLL中定義的函數原型,然後聲明。
2
顯式的運行時連結
隱式連結雖然實現較簡單,但除了必須的*.dll檔案外還需要DLL的*.h檔案和*.lib檔案,在那些只提供*.dll檔案的場合就無法使用,而只能採用顯式連結的方式。這種方式通過調用API函數來完成對DLL的載入與卸載,其能更加有效地使用記憶體,在編寫大型應用程式時往往採用此方式。這種方法編程具體實現步驟如下:
①使用Windows API函數Load Library或者MFC提供的AfxLoadLibrary將DLL模組映像到進程的記憶體空間,對DLL模組進行動態載入。
②使用GetProcAddress函數得到要調用DLL中的函數的指標。
③不用DLL時,用Free Library函數或者AfxFreeLibrary函數從進程的地址空間顯式卸載DLL。
例:在應用程式中調用dll檔案
——在應用程式中要首先裝入dll後才能調用匯出表中的函數,例如用mfc
建立基於對話方塊的工程test,並在對話方塊上放置"load"按鈕,先添加裝載代碼。
1.首先在testdlg.cpp的首部添加變數設定代碼:
//設定全域變數glibsample用於儲存dll控制代碼
hinstance glibsample=null;
//第二個變數showme是指向dll
庫中showme()函數的指標
typedef int(* showme)(void);
showme showme;
2.利用classwizard為"load"按鈕添加裝載dll的代碼
void ctestdlg::onloadbutton()
{
//要添加的代碼如下
if(glibmydll!=null)
{
messagebox("the sample.dll has already been load.");
return;
}
//裝載sample.dll,未加路徑,將在三個預設路徑中尋找 (1)windows的系統目錄:/windows/system;
//(2)dos中path所指出的任何目錄;
//(3)程式所在的目錄;
glibsample=loadlibrary("sample.dll");
//返回dll中showme()函數的地址
showme=(showme)GetProcAddress(glibsample,"showme");
//************************************************************************************************************************************************************************************
//************************************************************************************************************************************************************************************
應用程式使用DLL可以採用兩種方式:一種是隱式連結,另一種是顯式連結。在使用DLL之前首先要知道DLL中函數的結構資訊。Visual C++6.0在VC/bin目錄下提供了一個名為Dumpbin.exe的小程式,用它可以查看DLL檔案中的函數結構。另外,Windows系統將遵循下面的搜尋順序來定位DLL: 1.包含EXE檔案的目錄,2.進程的當前工作目錄, 3.Windows系統目錄, 4.Windows目錄,5.列在Path環境變數中的一系列目錄。
1.隱式連結
隱式連結就是在程式開始執行時就將DLL檔案載入到應用程式當中。實現隱式連結很容易,只要將匯入函數關鍵字_declspec(dllimport)函數名等寫到應用程式相應的標頭檔中就可以了。下面的例子通過隱式連結調用MyDll.dll庫中的Min函數。首先產生一個項目為TestDll,在DllTest.h、DllTest.cpp檔案中分別輸入如下代碼:
//Dlltest.h
#pragma comment(lib,"MyDll.lib")
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
//TestDll.cpp
#include
#include"Dlltest.h"
void main()
{int a;
a=min(8,10)
printf("比較的結果為%d/n",a);
}
在建立DllTest.exe檔案之前,要先將MyDll.dll和MyDll.lib拷貝到當前工程所在的目錄下面,也可以拷貝到windows的System目錄下。如果DLL使用的是def檔案,要刪除TestDll.h檔案中關鍵字extern "C"。TestDll.h檔案中的關鍵字Progam commit是要Visual C+的編譯器在link時,連結到MyDll.lib檔案,當然,開發人員也可以不使用#pragma comment(lib,"MyDll.lib")語句,而直接在工程的Setting->Link頁的Object/Moduls欄填入MyDll.lib既可。
2.顯式連結
顯式連結是應用程式在執行過程中隨時可以載入DLL檔案,也可以隨時卸載DLL檔案,這是隱式連結所無法作到的,所以顯式連結具有更好的靈活性,對於解釋性語言更為合適。不過實現顯式連結要麻煩一些。在應用程式中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動態連結程式庫調進來,動態連結程式庫的檔案名稱即是上述兩個函數的參數,此後再用GetProcAddress()擷取想要引入的函數。自此,你就可以象使用如同在應用程式自訂的函數一樣來調用此引入函數了。在應用程式退出之前,應該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動態連結程式庫。下面是通過顯式連結調用DLL中的Max函數的例子。
#include
#include
void main(void)
{
typedef int(*pMax)(int a,int b);
typedef int(*pMin)(int a,int b);
HINSTANCE hDLL;
PMax Max
HDLL=LoadLibrary("MyDll.dll");//載入動態連結程式庫MyDll.dll檔案;
Max=(pMax)GetProcAddress(hDLL,"Max");
A=Max(5,8);
Printf("比較的結果為%d/n",a);
FreeLibrary(hDLL);//卸載MyDll.dll檔案;
}
在上例中使用類型定義關鍵字typedef,定義指向和DLL中相同的函數原型指標,然後通過LoadLibray()將DLL載入到當前的應用程式中並返回當前DLL檔案的控制代碼,然後通過GetProcAddress()函數擷取匯入到應用程式中的函數指標,函數調用完畢後,使用FreeLibrary()卸載DLL檔案。在編譯器之前,首先要將DLL檔案拷貝到工程所在的目錄或Windows系統目錄下。
使用顯式連結應用程式編譯時間不需要使用相應的Lib檔案。另外,使用GetProcAddress()函數時,可以利用MAKEINTRESOURCE()函數直接使用DLL中函數出現的順序號,如將GetProcAddress(hDLL,"Min")改為GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函數Min()在DLL中的順序號是2),這樣調用DLL中的函數速度很快,但是要記住函數的使用序號,否則會發生錯誤。
編程時用ad.h,ad.lib,放在項目目前的目錄裡
在標頭檔中加入#include "ad.h"
在Project Setting-->Link-->Object/library modules
加入ad.lib
執行時將ad.dll跟你的程式放在同一目錄