C++ 创建引用DLL
親手嘗試了一下創(chuàng)建并引用DLL一種方式,記錄一下過程。
使用的語言為C++,IDE使用的為VS2010
說一下我自己的理解。程序編譯是指編譯當(dāng)前程序中寫的代碼,當(dāng)然應(yīng)用程序中有可能還會包含著已經(jīng)其他的開發(fā)人員開發(fā)的代碼,這時不需要編譯他們的代碼,因為有可能他們就沒給你源代碼,這個時候要把他們提供的代碼鏈接到應(yīng)用程序中,怎么用呢。一般來說是會提供一個lib文件,或dll文件。簡單說一下認(rèn)識。
有兩種方式把這些lib文件或者dll文件引進(jìn)過來,一種是靜態(tài)鏈接,一種是動態(tài)鏈接。
靜態(tài)鏈接是把這些lib和dll直接加入到應(yīng)用程序生成的exe文件中,這樣的話會導(dǎo)致exe比較大,占用比較大的存儲空間。lib文件中直接就是把obj文件直接壓進(jìn)lib文件中,在使用的過程中把lib和.h加入到工程中,直接編譯就可以了。
而開發(fā)靜態(tài)庫時, 你只需要在頭文件聲明函數(shù)或者類,然后再實現(xiàn)文件里實現(xiàn)函數(shù)或類就可以了。
使用的時候,.h頭文件加到工程里,然后再指定要鏈接的.lib文件,就可以了。
可用#pragma comment(lib, "libfilepath")來指定要鏈接的靜態(tài)庫。或者在project->dependency里設(shè)置。
libfilepath可以設(shè)定為相對路徑使用.\ ?..\等來指定路徑。
動態(tài)鏈接使用dll文件,這個文件實際上里面都是函數(shù)的描述和定義,其實和exe文件很相似,但是它不能單獨(dú)的執(zhí)行。這個文件不能單獨(dú)使用,一般要和lib文件一起配合使用,這個lib文件就和靜態(tài)的不是一個意思,這個lib文件里面不是包括obj文件,而是對dll中的函數(shù)的位置,參數(shù)等的描述,作用類似于h文件,對dll中函數(shù)進(jìn)行說明。這個dll文件不會加入到exe文件中,所以在程序執(zhí)行的時候必須有exe和dll文件共同存在。這種動態(tài)鏈接的好處是
1、擴(kuò)展了應(yīng)用程序的特性;
2、可以用許多種編程語言來編寫;
3、簡化了軟件項目的管理;
4、有助于節(jié)省內(nèi)存;
5、有助于資源共享;
6、有助于應(yīng)用程序的本地化;
7、有助于解決平臺差異;
靜態(tài)鏈接庫和動態(tài)庫(DLL)的另外一個區(qū)別在于靜態(tài)鏈接庫中不能再包含其他的動態(tài)鏈接庫或者靜態(tài)庫,而在動態(tài)鏈接庫中還可以再包含其他的動態(tài)或靜態(tài)鏈接庫。
本文主要是針對于動態(tài)鏈接進(jìn)行介紹
先說一下創(chuàng)建DLL
1.先創(chuàng)建工程,導(dǎo)出符號要勾選上
2.代碼如下
3.編譯后生成的了dll和lib文件
動態(tài)鏈接的使用方式又分為兩種,一種稱為靜態(tài)的,一種稱為動態(tài)的。
開發(fā)和使用dll需注意三種文件:
1)dll頭文件
它是指dll中說明輸出的類或符號原型或數(shù)據(jù)結(jié)構(gòu)的.h文件。當(dāng)其它應(yīng)用程序調(diào)用dll時,需要將該文件包含入應(yīng)用程序的源文件中。
2)dll的引入庫文件(.lib)
它是dll在編譯、鏈接成功后生成的文件。主要作用是當(dāng)其它應(yīng)用程序調(diào)用dll時,需要將該文件引入應(yīng)用程序。否則,dll無法引入。
3)dll文件(.dll)
它是應(yīng)用程序調(diào)用dll運(yùn)行時,真正的可執(zhí)行文件。dll應(yīng)用在編譯、鏈接成功后,.dll文件即存在。開發(fā)成功后的應(yīng)用程序在發(fā)布時,只需要有.exe文件和.dll文件,不必有.lib文件和dll頭文件。
從使用的角度上來看,如何靜態(tài)調(diào)用,則要用到lib文件,而動態(tài)調(diào)用則不用,只需要DLL文件就夠了。
DLL的調(diào)用分為動態(tài)和靜態(tài)兩種:動態(tài)調(diào)用和靜態(tài)調(diào)用。動態(tài)調(diào)用方式的特點(diǎn)是完全由編程者用 API 函數(shù)加載和卸載 DLL,程序員可以決定 DLL 文件何時加載或不加載,顯式鏈接在運(yùn)行時決定加載哪個 DLL 文件。
動態(tài)調(diào)用,即顯式調(diào)用方式,是由編程者用API函數(shù)加載和卸載DLL來達(dá)到調(diào)用DLL的目的,比較復(fù)雜,但能更加有效地使用內(nèi)存,是編制大型應(yīng)用程序時的重要方式。在Windows系統(tǒng)中,與動態(tài)庫調(diào)用有關(guān)的函數(shù)包括:
①LoadLibrary(或MFC 的AfxLoadLibrary),裝載動態(tài)庫。
②GetProcAddress,獲取要引入的函數(shù),將符號名或標(biāo)識號轉(zhuǎn)換為DLL內(nèi)部地址。
③FreeLibrary(或MFC的AfxFreeLibrary),釋放動態(tài)鏈接庫。
靜態(tài)調(diào)用,也稱為隱式調(diào)用,由編譯系統(tǒng)完成對DLL的加載和應(yīng)用程序結(jié)束時DLL卸載的編碼(Windows系統(tǒng)負(fù)責(zé)對DLL調(diào)用次數(shù)的計數(shù)),調(diào)用方式簡單,能夠滿足通常的要求。通常采用的調(diào)用方式是把產(chǎn)生動態(tài)連接庫時產(chǎn)生的.LIB文件加入到應(yīng)用程序的工程中,想使用DLL中的函數(shù)時,只須在源文件中聲明一下。
LIB文件包含了每一個DLL導(dǎo)出函數(shù)的符號名和可選擇的標(biāo)識號以及DLL文件名,不含有實際的代碼。Lib文件包含的信息進(jìn)入到生成的應(yīng)用程序中,被調(diào)用的DLL文件會在應(yīng)用程序加載時同時加載在到內(nèi)存中。
靜態(tài)調(diào)用方式的特點(diǎn)是由編譯系統(tǒng)完成對DLL的加載和應(yīng)用程序結(jié)束時 DLL 的卸載。當(dāng)調(diào)用某DLL的應(yīng)用程序結(jié)束時,若系統(tǒng)中還有其它程序使用該 DLL,則Windows對DLL的應(yīng)用記錄減1,直到所有使用該DLL的程序都結(jié)束時才釋放它。靜態(tài)調(diào)用方式簡單實用,但不如動態(tài)調(diào)用方式靈活。
靜態(tài)加載過程
1.先建一個工程
2.現(xiàn)在要設(shè)置工程了,這個環(huán)節(jié)很重要。
先把MyDLL.dll中的聲明文件MyDLL.h加入到T_MyDLL工程中,如果這里不這么設(shè)置的話,則要MyDLL.h引入到工程中。實際上這個文件只是在編譯中用到,最終的exe不需要這個文件,所以這里建議通過在工程中設(shè)定一下。在工程上點(diǎn)右鍵,屬性,進(jìn)行設(shè)置,在“附加包含目錄”中把路徑設(shè)成剛剛MyDLL的目錄,注意路徑要到MyDLL.h這個路徑下。
這里介紹這里設(shè)置的“附加包含目錄”。
這里簡單說一下和上面的“VC++目錄”的區(qū)別
“VC++ Directories -> Include Directories” : Directory settings displayed in the window are the directories that Visual Studio will search for include files referred to in your source code files. Corresponds to environment variable INCLUDE. More information : http://msdn.microsoft.com/en-us/library/t9az1d21(v=vs.80).aspx
“C/C++ -> General -> Additional Include Directories”: The directory to be added to the list of directories searched for include files. More information : http://msdn.microsoft.com/en-us/library/73f9s62w(v=vs.80).aspx
下面那個鏈接講的比較清楚了:
The compiler searches for directories in the following order:
1.Directories containing the source file.
2.Directories specified with the /I option, in the order that CL encounters them.
3.Directories specified in the INCLUDE environment variable.
order2中的/I是由C/C++ -> General -> Additional Include Directories設(shè)置的。
order3中的INCLUDE是由VC++ Directories -> Include Directories設(shè)置的。
設(shè)置完了MyDLL.h的路徑后還要設(shè)置依賴文件MyDLL.lib的路徑,因為MyDLL.lib是對DLL文件的說明,所以沒有設(shè)置這個文件的路徑的話,在程序鏈接的時候會找不到對應(yīng)的MyDLL.dll中定義的函數(shù)。
這時不用設(shè)置MyDLL.dll文件,你也可以把這個dll文件拷到和T_MyDLLDlg.cpp文件同一個路徑下。
設(shè)計的界面如下。
代碼如下
效果就是實現(xiàn)一個簡單的加法動作。
編譯完生成一個exe文件
這時候把.exe文件和.dll文件拷到一個文件夾里,就可以執(zhí)行了。如果不放.dll文件的話單執(zhí)行exe的話是不能執(zhí)行的。
動態(tài)鏈接的例子,用到上面的3個函數(shù)就可以了,這里不過多介紹。
動態(tài)調(diào)用要知道DLL的文件路徑,并且知道接口函數(shù)的類型及參數(shù),并不需要依賴到.h文件、lib文件等內(nèi)容。
但是,要動態(tài)調(diào)用DLL里面的函數(shù)的話,那么在該函數(shù)的前面必須要添加一個extern "C"(聲明為C編譯、連接方式的外部函數(shù)),不然動態(tài)調(diào)用會找不到這個函數(shù)地址的。
如下,在MyDLL.h中添加下列代碼:
extern "C" MYDLL_API int Add(int a, int b);
在MyDLL.cpp中添加下列代碼:
MYDLL_API int Add(int a, int b)
{
return a + b;
}
創(chuàng)建一個MFC對話框應(yīng)用程序,然后在初始化函數(shù)中加入下列代碼:
{
CDialog::OnInitDialog();
// ....省略其他代碼
//加載MyDLL.dll
HINSTANCE hDllInst = AfxLoadLibrary(_T("MyDLL.dll"));
//判斷是否加載成功
if(hDllInst)
{
? ? //根據(jù)DLL里面的封裝函數(shù)來定義函數(shù)指定
typedef int(*pAdd)(int ,int);
pAdd myAdd;
? ? ? ? //根據(jù)函數(shù)名來從已加載的DLL中獲取函數(shù)地址并賦值
myAdd = (pAdd)GetProcAddress(hDllInst, "Add");
? ? ? ? //判斷是否獲取成功
if(myAdd != NULL)
{
? ? ? ? ? ? ?//調(diào)用該函數(shù)
int a = myAdd(10, 20);
CString str;
str.Format(_T("%d"), a);
TRACE(str);
}
? ? ? ? //釋放加載的DLL
AfxFreeLibrary(hDllInst);
}
return TRUE;
}
轉(zhuǎn)載于:https://blog.51cto.com/mingsuper/1350943
總結(jié)
以上是生活随笔為你收集整理的C++ 创建引用DLL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android使用 LruCache 缓
- 下一篇: 【cocos2d-x从c++到js】16