DLL(Dynamic
Linkable Library)可以看成一些可以直接拿來(lái)用的變量、函數(shù)或類的集合。在庫(kù)的發(fā)展史上經(jīng)歷了“無(wú)庫(kù)-靜態(tài)鏈接庫(kù)-動(dòng)態(tài)鏈接庫(kù)”的時(shí)代。
靜態(tài)鏈接庫(kù)與動(dòng)態(tài)鏈接庫(kù)都是共享代碼的方式,如果采用靜態(tài)鏈接庫(kù),則無(wú)論你愿不愿意,lib中的指令都被直接包含在最終生成的EXE文件中了。但是若使用DLL,該DLL不必被包含在最終EXE文件中,EXE文件執(zhí)行時(shí)可以“動(dòng)態(tài)”地引用和卸載這個(gè)與EXE獨(dú)立的DLL文件。靜態(tài)鏈接庫(kù)和動(dòng)態(tài)鏈接庫(kù)的另外一個(gè)區(qū)別在于靜態(tài)鏈接庫(kù)中不能再包含其他的動(dòng)態(tài)鏈接庫(kù)或者靜態(tài)庫(kù),而在動(dòng)態(tài)鏈接庫(kù)中還可以再包含其他的動(dòng)態(tài)或靜態(tài)鏈接庫(kù)。
對(duì)動(dòng)態(tài)鏈接庫(kù),我們還需建立如下概念:
(1)DLL 的編制與具體的編程語(yǔ)言及編譯器無(wú)關(guān)
只要遵循約定的DLL接口規(guī)范和調(diào)用方式,用各種語(yǔ)言編寫(xiě)的DLL都可以相互調(diào)用。譬如Windows提供的系統(tǒng)DLL(其中包括了Windows的API),在任何開(kāi)發(fā)環(huán)境中都能被調(diào)用,不在乎其是Visual Basic、Visual C++還是Delphi。
(2)動(dòng)態(tài)鏈接庫(kù)隨處可見(jiàn)
我們?cè)?span lang="EN-US">Windows目錄下的system32文件夾中會(huì)看到kernel32.dll、user32.dll和gdi32.dll,windows的大多數(shù)API都包含在這些DLL中。kernel32.dll中的函數(shù)主要處理內(nèi)存管理和進(jìn)程調(diào)度;user32.dll中的函數(shù)主要控制用戶界面;gdi32.dll中的函數(shù)則負(fù)責(zé)圖形方面的操作。
一般的程序員都用過(guò)類似MessageBox的函數(shù),其實(shí)它就包含在user32.dll這個(gè)動(dòng)態(tài)鏈接庫(kù)中。由此可見(jiàn)DLL對(duì)我們來(lái)說(shuō)其實(shí)并不陌生。
(3)VC動(dòng)態(tài)鏈接庫(kù)的分類
Visual C++支持三種DLL,它們分別是Non-MFC DLL(非MFC動(dòng)態(tài)庫(kù))、MFC Regular DLL(MFC規(guī)則DLL)、MFC Extension DLL(MFC擴(kuò)展DLL)。
非MFC動(dòng)態(tài)庫(kù)不采用MFC類庫(kù)結(jié)構(gòu),其導(dǎo)出函數(shù)為標(biāo)準(zhǔn)的C接口,能被非MFC或MFC編寫(xiě)的應(yīng)用程序所調(diào)用;MFC規(guī)則DLL 包含一個(gè)繼承自CWinApp的類,但其無(wú)消息循環(huán);MFC擴(kuò)展DLL采用MFC的動(dòng)態(tài)鏈接版本創(chuàng)建,它只能被用MFC類庫(kù)所編寫(xiě)的應(yīng)用程序所調(diào)用。
一. Non-MFC DLL的編寫(xiě)步驟:
1、新建項(xiàng)目->
win32項(xiàng)目->應(yīng)用程序設(shè)置->應(yīng)用程序類型:
選擇DLL,完成。
2、添加變量、函數(shù)或類到庫(kù)中,例如:
/* 文件名:xxx.h */
#ifndef XXX_H
#define XXX_H
#ifndef LIB_EXPORTS
#define
LIB_API __declspec(dllimport)
#else
#define LIB_API __declspec(dllexport)
#endif
extern "C" int LIB_API max(int x, int y);
#endif
/* 文件名:xxx.cpp */
#include "xxx.h"
int add(int x, int y)
{
return x > y ? x y;
}
在動(dòng)態(tài)庫(kù)的工程屬性->C/C++->預(yù)處理器->預(yù)處理器定義里,添LIB_EXPORTS。 編譯。
3. 創(chuàng)建另外一個(gè)工程,來(lái)調(diào)用該庫(kù)
調(diào)用DLL有兩種方式:
(1) 顯式調(diào)用
typedef int (*pDllFunc)(int , int);
HINSTANCE hDll =
LoadLibrary(_T("xxx.dll"));
pDllFunc pMax = NULL;
if (hDll) {
pMax = (pDllFunc)GetProcAddress(hDll, "max");
if (pMax) {
std::cout <<
pMax(21, 22) << std::endl;
}
}
if (hDll) {
FreeLibrary(hDll);
}
(2) 隱式調(diào)用
首先,包含該庫(kù)的頭文件
其次,鏈接動(dòng)態(tài)庫(kù),把保存庫(kù)的目錄添加到工程屬性->連接器->常規(guī)->附加庫(kù)目錄,在工程屬性->連接器->輸入->附加依賴項(xiàng)添加庫(kù)的lib文件名 或者在程序中用
#pragma comment(lib, ".\\lib\\xxx.lib")添加(若已經(jīng)添加庫(kù)的目錄,就不需要相當(dāng)路徑,直接寫(xiě)lib文件名“xxx.lib”)
然后就可以直接用變量,函數(shù)或者類了。
注意:隱式調(diào)用和顯示調(diào)用的區(qū)別:
隱式調(diào)用的方法比較方便,但DLL改變后,應(yīng)用程序須從新編譯。并且,所有所調(diào)用的DLL在應(yīng)用程序加載的同時(shí)被加載到內(nèi)存中,當(dāng)應(yīng)用程序調(diào)用的DLL比較多時(shí),裝入的過(guò)程十分慢。顯式調(diào)用則比較靈活,但比較麻煩.
二 MFC Regular DLL 的編寫(xiě)步驟:
1、新建項(xiàng)目->MFC DLL->應(yīng)用程序設(shè)置->選擇DLL類型,完成。
注意:靜態(tài)鏈接MFC DLL和共享MFC DLL的區(qū)別:靜態(tài)鏈接把程序中要用的在MFC DLL里的東西全部編譯到創(chuàng)建的DLL中,體積會(huì)大一點(diǎn),但可以在沒(méi)有裝MFC的機(jī)器上運(yùn)行;通過(guò)共享創(chuàng)建的DLL體積小,但在沒(méi)有安裝MFC的機(jī)器上有可能不能運(yùn)行,因?yàn)闆](méi)有相應(yīng)的庫(kù)。
2、其他步驟和創(chuàng)建Non-MFC
DLL差不多。
三
MFC擴(kuò)展DLL
這里有比較詳細(xì)的介紹http://tech.163.com/06/0316/10/2CB2S3HP0009159F.html。