首页 > 代码库 > DLL的心得体会
DLL的心得体会
关于DLL,网上的资料很多,也很杂乱,我花了一天的时间,把各种版本都亲手试了试。加上自己的心得和体会,还是挺全面的。希望能对大家有所帮助。
DLL:动态链接库。
DLL是与exe分开的,当exe执行的时候才去找DLL中函数,而普通的lib文件是链接的时候就已经加载到exe中的。
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。
动态链接与静态链接的不同之处在于:动态链接允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。
Lib文件是已经编译好的,但没有链接,所以程序链接的时候就会去找lib
Dll文件是已经编译好,且链接好的,所以程序编译和链接的时候都和它没关系,只有执行的时候才去找他。
应用程序和 DLL 之间的区别
应用程序可有多个同时在系统上运行的实例,而 DLL只能有一个实例。
应用程序可以拥有堆栈、共用内存、文件句柄、消息队列这样的事物,而 DLL不能。
使用 DLL 的优点
1节省内存和减少交换操作。很多进程可以同时使用一个 DLL,在内存中共享该 DLL的一个副本。相反,对于每个用静态链接库生成的应用程序,Windows必须在内存中加载库代码的一个副本。
2节省磁盘空间。许多应用程序可在磁盘上共享 DLL的一个副本。相反,每个用静态链接库生成的应用程序均具有作为单独的副本链接到其可执行图像中的库代码。
3升级到 DLL更为容易。当 DLL 中的函数发生更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相反,静态链接的对象代码要求在函数更改时重新链接应用程序。
4提供售后支持。例如,可修改显示器驱动程序 DLL以支持当初交付应用程序时不可用的显示器。
5DLL可以被其他DLL调用,而lib库不可以被其他lib调用。
生成DLL文件
有两种方法:
在生成 DLL时,创建一个模块定义 (.def)文件并使用该 .def文件。。
在函数的定义中使用 __declspec(dllexport) 关键字。
在此之前我们要创建一个DLL工程:new project->C++->win32 consoleapplication->DLL->文件名:Mydll
Dllmain.cpp是入口函数,不用管。主要是在Mydll.cpp中写代码
1. 使用__declspec(dllexport) 关键字生成DLL
若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。
若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边。
例如:该动态链接库中有两个函数,分别用来实现得到两个数的最大和最小数。
//Mydll.h
extern "C" _declspec(dllexport) int Max(int a, intb);
extern "C" _declspec(dllexport) int Min(int a, intb);
//Mydll.cpp
#include”Mydll.h”
int Max(int a, int b)
{
if(a>=b)returna;
else
return b;
}
int Min(int a, int b);
{
if(a>=b)returnb;
else
return a;
}
然后build一下,就在debug中生成了Mydll.dll和Mydll.lib文件。
2. 使用def文件生成DLL
在Mydll.cpp中写好自己要导出的函数(或类或变量)的定义.就是普通定义,不加什么修饰符的。
然后new一个def文件,在def文件中写:
LIBRARY MyDll(是包含要导出函数的文件名)
EXPORTS
函数名(要导出的函数名,可以有多个)
函数名
然后build一下,就在debug中生成了Mydll.dll和Mydll.lib文件。
注:这里为何生成了lib文件?
这里的lib文件是DLL文件中函数名称和地址,如果是隐式链接的话,链接的时候程序会链接DLL的导入库文件(就是这个lib文件)。在程序执行时,程序才会根据导入库文件中的函数地址去到DLL中寻找函数体。
DLL<-----àLIB<-----àEXE
注:DLL内部函数的调用是不用加什么_declspec(dllexport)的,想一想DLL的原理就知道原因了。
链接DLL的方法(如何使用DLL)
注:编译时是和库文件没有关系的
有两种类型的链接:隐式链接和显式链接。(隐式链接要把生成DLL的程序会产生DLL文件和导入文件lib放到当前工程目录下,显示链接只需要DD文件就可以了)
隐式链接:
隐式链接就是在程序开始执行时就将DLL文件加载到应用程序当中。实现隐式链接很容易,只要将导入函数关键字_declspec(dllimport)函数名等写到应用程序相应的头文件中就可以了。
为隐式链接到 DLL,可执行文件必须从 DLL的提供程序获取下列各项:
1包含导出函数和/或 C++类的声明的头文件(.h文件)。或使用__declspec(dllimport)
将函数的定义导入进来
2要链接的导入库(.LIB files)。(生成 DLL时链接器创建导入库。)
3实际的 DLL(.dll文件)。
例如:
// TestDll.h
#pragma comment(lib,"MyDll.lib")
!!这一步开发人员也可以不使用#pragma comment(lib,"MyDll.lib")语句,而直接在工程的Setting->Link页的Object/Moduls栏填入MyDll.lib既可
extern "C" _declspec(dllimport) int Min(int a,intb);
!!如果要导出的是变量:则
extern _declspec(dllimport) inta;因为只有加上extern,这才是声明。
这部分也可以用
extern “ C” {
#include”Mydll.h”
}
来代替,效果是一样的。(注意要把MyDll.h拷到此工程下).推荐这样使用。
//TestDll.cpp
#include<iostream>
#include<Windows.h>
#include"Dlltest.h"
void main()
{int a;
a=Min(8,10)
cout<<a<<endl;
}
/////////////////////////////////////////////////////////////
静态链接体会:
1. Dll和lib不是都已经有了吗,为何还需要#include<.h>或dllimport。
因为dll需要静态导入,所以需要lib导入库,由于lib导入库中的函数名都是c编译好的,函数名都是_funcname形式的,所以需要#include<..h>或dllimport函数名,这样编译时才会生成函数名类似_funcname形式的。然后链接时才会正确链接lib导入库。
2. 为何#include头文件中要加extern “C”或者_declspec(dllimport)前要加extern “C”。
因为lib导入库是用C语言编译好的,函数名形如_funcname.如果用C++来编译头文件或_declspec(dllimport)后面的函数名,由于C++支持多态,所以它编译函数名时要把函数的参数个数、参数类型一起柔和在一起,则函数名会是_func_int_float类似的东西。而这样的函数名显示与lib导入库的函数名匹配不了的。
//////////////////////////////////////////////////////////////
显式链接:
显式链接是应用程序在执行过程中随时可以加载DLL文件,也可以随时卸载DLL文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,对于解释性语言更为合适。
在显式链接下,应用程序必须进行函数调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:
1调用 LoadLibrary(或相似的函数)以加载 DLL 和获取模块句柄。
2调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引用,故无需与导入库链接。
3使用完 DLL后调用 FreeLibrary。
#include<iostream>
#include<Windows.h>
using namespace std;
void main(void)
{
typedef int(*pMax)(int a,int b);
HINSTANCE hDLL;
pMax Max;
hDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;
Max=(pMax)GetProcAddress(hDLL,"Max");
int a=Max(5,8);
cout<<a<<endl;
FreeLibrary(hDLL);//卸载MyDll.dll文件;
System(“pause”);
}
!!!!
查看lib文件、dll文件,使用命令行:
>dumpbin /exports xxx.lib/xxx.dll
DLL的心得体会