动态库(dll)

DinS          Written on 2017/6/4

一、DLL概述

DLL = Dynamic Linkable Library 中文:动态链接库。

之所以叫动态,是因为跟lib相比有两个特点:独立于调用程序,并且dll中还可以包含dll或者lib。

使用dll比使用lib复杂,确保你阅读过《静态库(lib)》并理解了其内容。

二、制作DLL

1.__declspec(dllexport) 方式

新建控制台项目,类型选择DLL,然后跟静态库类似,只不过在函数前加上奇怪的东西。

加的内容说明该函数是用于导出的,其他程序可以使用。相应的,不加内容的就是dll自己使用的函数。

右键项目->生成,会得到lib和.dll。其他的没什么用

2.def文件方式

仿照上例新建DLL项目,写代码,只不过这次函数前不加奇怪的东西。
写完.h和.cpp后添加项->def文件。

按照规则填写def文件
(1)LIBRARY语句说明.def文件相应的DLL;
(2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);
(3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。

正常情况下编译器会自动关联.def。保险起见可以在项目属性->链接器->输入里找到模块定义文件,这里应该是对应的.def

右键项目->生成,就能够找到对应的dll和lib文件。

3.小结:与lib相比,制作dll时我们需要显式指定导出的函数,不管是__declspec(dllexport)还是def方式,我们做的都是指定某些函数将要被导出。

相比之下def的方式更加简便。

不论如何,最终得到的都是三件套:.h .lib .dll。

三、使用DLL

1.  __declspec(dllimport)方式

同理新建一个项目,把三件套拷贝到项目里。


设置项目属性,与导入lib的方式一样。
注意设置属性时并没有对dll文件的显示引用,仍然只设置.h .lib。

在使用函数前声明一大串东西,注意到这个声明跟dll里的声明的区别在dllimport

然后就可以正常使用dll里的函数了。

这种调用dll的方式称为静态调用,静态调用方式的特点是由编译系统完成对DLL的加载和应用程序结束时 DLL 的卸载。使用简单不过灵活性不强。通常而言使用这种方法可以满足需求。

2.def方式

如果制作dll时使用了def方式,那就简便多了。

同样将三件套导入项目。只不过这次不需要声明函数了,包含.h后就可以直接使用。

3.动态加载DLL

以上介绍的都是静态加载DLL的方式,即利用VS的项目属性,在项目一开始就加载全部DLL
如果希望加载方式更加灵活,让程序员拥有更大权力,那么可以使用动态加载的方式。

动态加载的方式要更加复杂,要遵循几个步骤:
1.声明头文件<windows.h>
2.然后用typedef定义一个指针函数类型
3.定一个句柄实例,用来取DLL的实例地址
格式为hdll=LoadLibrary(“DLL地址”)
这里字符串类型是LPSTR,当是unicode字符集的时候会不行,因此要在配置-属性-常规里面把默认字符集“unicode”改成支持多字符扩展即可。
4.取的地址要判断,返回的句柄是否为空,如果为无效句柄,那么要释放加载DLL所占用的内存。
5.然后定义一个函数指针,用来获取你要用的函数地址
6.然后通过函数指针来调用函数。
7.最后调用结束后释放句柄

注意这个过程中没有.h和lib的任何事情,也就是说用动态加载的方式可以仅仅使用dll一个文件就完成调用。

完整的代码示例如下:

结果:

四、调试DLL

因为DLL不能够直接运行,所以我们通常在同一个工程中单独建立一个项目调用dll观察结果。
但是这种调试方法仍然有局限,比如说不能够在dll的代码中打断点,这样不利于调试。

当然是有方法解决这个困难的,只需要做如下几件事即可。
首先做一个调用dll的exe,并编译。
找到该exe,记住路径

之后进入需要调试的dll项目,在属性->调试中,命令项输入刚才的exe路径

然后把dll设置为启动项

然后运行,此时设置的断点就命中了

这样可以像正常的项目一样调试dll了。

五、有关DLL的其他说明

lib的注意事项同样适用于dll,所以如果调用失败了可以去看《静态库(lib)》的相关内容。

因为dll是独立于调用程序的,因此如何找到dll文件的位置就成为了一个问题。Windows有如下的搜寻方式:exe同级目录->当前目录->系统目录(通常是Windows\System32)->Windows目录,另外还有系统环境PATH下注册的目录。如果都找不到就会报错:找不到指定dll。

最后dll是windows下才有的,如果做跨平台的程序那么就不要使用dll了。本人一般都不会使用操作系统提供的功能。

有关MFC的dll见《带MFC的dll》。