一直对动态链接库这个东西很陌生,今天刚好调试别人写的一个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民工的命咋就这么苦哩。