一直對動態鏈接庫這個東西很陌生,今天剛好調試別人寫的一個DLL項目,順便就來研究一下下。
動態鏈接庫的原理,好處那些就先不說了,直接來看怎么使用。
首先寫一個動態鏈接庫,其中
__declspec(dllexport)是用于MS編譯器的一個關鍵字,用來將DLL中的內容導出而不需要.def文件了。
下面的cpp里就函數的定義了,DllMain函數跟普通的win32 console的main函數很像。
使用cl /c DLLImplement.cpp
link /dll DLLImplement.obj
就可以得到一個DLLImplement.dll順便也會導出一個DLLImplement.lib這個跟靜態鏈接庫很像的東西,實際上它的作用只是導出那些方法和變量的名字。
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方法/使用導出的lib配合頭文件。
第一種太麻煩這里不介紹,只說明一下后兩種的使用方法。
?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?}
這種調用方法屬于顯示調用,使用的時候需要知道DLL文件的路徑,還有DLL里面的方法的名字,還是有點不太方便。更多的時候,都是使用最后一種隱式調用的方法,即配合頭文件和導出的lib,需要在進行鏈接的時候加入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?}
到這里對DLL有了一個大概的感性認識,具體的理論性的知識,等有機會慢慢再寫出來。
抱怨一句,最近有點懶了,想要寫的日志都沒寫。
找實習也麻煩,寫代碼肩膀脖子酸痛。
IT民工的命咋就這么苦哩。