一直對(duì)動(dòng)態(tài)鏈接庫(kù)這個(gè)東西很陌生,今天剛好調(diào)試別人寫(xiě)的一個(gè)DLL項(xiàng)目,順便就來(lái)研究一下下。
動(dòng)態(tài)鏈接庫(kù)的原理,好處那些就先不說(shuō)了,直接來(lái)看怎么使用。
首先寫(xiě)一個(gè)動(dòng)態(tài)鏈接庫(kù),其中
__declspec(dllexport)是用于MS編譯器的一個(gè)關(guān)鍵字,用來(lái)將DLL中的內(nèi)容導(dǎo)出而不需要.def文件了。
下面的cpp里就函數(shù)的定義了,DllMain函數(shù)跟普通的win32 console的main函數(shù)很像。
使用cl /c DLLImplement.cpp
link /dll DLLImplement.obj
就可以得到一個(gè)DLLImplement.dll順便也會(huì)導(dǎo)出一個(gè)DLLImplement.lib這個(gè)跟靜態(tài)鏈接庫(kù)很像的東西,實(shí)際上它的作用只是導(dǎo)出那些方法和變量的名字。
1?extern?"C"
2?{
3?????__declspec(dllexport)?void?Set(int?i);
4?????__declspec(dllexport)?int?Get();
5?????__declspec(dllexport)?void?SayHello();
6?
7?????int?value;
8?}
?1?#include?<iostream>
?2?#include?<objbase.h>
?3?#include?"DLLHeader.h"
?4?
?5?
?6?void?Set(int?i)
?7?{
?8?????value?=?i;
?9?}
10?int?Get()
11?{
12?????return?value;
13?}
14?void?SayHello()
15?{
16?????std::cout<<"Hello,?I'm?DLL,?value?is?"<<value<<std::endl;
17?}
18?
19?
20?BOOL?APIENTRY?DllMain(HANDLE?hModule,?DWORD?dwReason,?void*?lpReserved)
21?{
22?????HANDLE?g_hModule;
23?
24?????switch(dwReason)
25?????{
26?????case?DLL_PROCESS_ATTACH:
27????????std::cout<<"DLL?is?attached!"<<std::endl;
28????????g_hModule?=?(HINSTANCE)hModule;
29????????break;
30?
31?????case?DLL_PROCESS_DETACH:
32????????std::cout<<"DLL?is?detached!"<<std::endl;
33????????g_hModule=NULL;
34????????break;
35?????}
36?
37?????return?TRUE;
38?}
39?
使用DLL的方法,有3種:使用def文件/使用LoadLibrary和GetProcAddress方法/使用導(dǎo)出的lib配合頭文件。
第一種太麻煩這里不介紹,只說(shuō)明一下后兩種的使用方法。
?1?#include?<iostream>
?2?#include?<windows.h>
?3?
?4?typedef?void?(*SET)(int);
?5?typedef?int?(*GET)(void);
?6?typedef?void?(*SAYHELLO)(void);
?7?
?8?int?main(int?argc,?char?**argv)
?9?{
10?????SET?pSet?=?0;
11?????GET?pGet?=?0;
12?????SAYHELLO?pSayHello?=?0;
13?
14?????HINSTANCE?hinst=::LoadLibrary("DLLImplement.dll");
15?????if?(0?==?hinst)
16?????{
17?????????std::cout<<"load?dll?failed!"<<std::endl;
18?????????return?-1;
19?????}
20?
21?????pSet?=?(SET)GetProcAddress(hinst,?"Set");
22?????pGet?=?(GET)GetProcAddress(hinst,?"Get");
23?????pSayHello?=?(SAYHELLO)GetProcAddress(hinst,?"SayHello");
24?
25?????if?(0?==?pSet?||?0?==?pGet?||?0?==?pSayHello)
26?????{
27?????????std::cout<<"get?function?failed!"<<std::endl;
28?????????return?-1;
29?????}
30?
31?????//ready?to?call?the?function
32?????(*pSet)(10);
33?????int?i?=?(*pGet)();
34?????std::cout<<"Get?value?from?dll,?value?is?"<<i<<std::endl;
35?????(*pSayHello)();
36?
37?????return?0;
38?}
這種調(diào)用方法屬于顯示調(diào)用,使用的時(shí)候需要知道DLL文件的路徑,還有DLL里面的方法的名字,還是有點(diǎn)不太方便。更多的時(shí)候,都是使用最后一種隱式調(diào)用的方法,即配合頭文件和導(dǎo)出的lib,需要在進(jìn)行鏈接的時(shí)候加入DLLImplement.lib即可,方法如下:
?1?#include?<iostream>
?2?#include?"DLLHeader.h"
?3?
?4?using?namespace?std;
?5?
?6?
?7?int?main?(int?argc,?char?**argv)
?8?{
?9?????Set(100);
10?????cout<<"Set?value?in?DLL"<<endl;
11?????int?i?=?Get();
12?????cout<<"Get?value?in?DLL,?value?is?"<<i<<endl;
13?
14?????SayHello();
15?????return?0;
16?}
到這里對(duì)DLL有了一個(gè)大概的感性認(rèn)識(shí),具體的理論性的知識(shí),等有機(jī)會(huì)慢慢再寫(xiě)出來(lái)。
抱怨一句,最近有點(diǎn)懶了,想要寫(xiě)的日志都沒(méi)寫(xiě)。
找實(shí)習(xí)也麻煩,寫(xiě)代碼肩膀脖子酸痛。
IT民工的命咋就這么苦哩。