第19章、动态链接库(DLL)
1. 动态链接库通常都不能直接运行,也不能接受消息,他们是一些独立的文件,是函数;
2. Windows API中所有的函数都包含在DLL中;其中有3个最重要的DLL:
1. Kernel32.dll:包含那些用于内存管理、进程和线程的函数;
2. User32.dll: 执行用户界面任务的函数(窗口的建立和消息的传送)
3. GDI32.dll : 它包含那些用于画图和显示文本的函数;
3.静态链接库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)
4.动态链接库:往往有两个文件,一个引入库(.lib)文件和一个DLL(.dll)文件;
注意:虽然这里的引用库也是.lib,但它是包含该DLL导出的函数和变量的符号名,而DLL文件包含该DLL实际的函数和数据;
4.应用程序如果要访问某个DLL中的函数,那么该函数必须是已经被导出的函数;
4. 为了查看一个DLL中有哪些导出的函数,可以利用VS提供的命令行工具:Dumpbin来实现;
如:dumpbin –exports dll1.dll
5. 为了让DLL导出一些函数,需要在每一个将要被导出的函数前面添加标识符:
_declspec(dllexport);
6. C++支持函数重载,对于重载的多个函数来说,其函数名都是一样的,为了加于区分,在编译链接时,C++会按照自己的规则篡改函数的名称。这一过程成为“名字改编”,有的书也成为“名字粉碎”;
不同的C++编译器会采用不同个规则进行名字的改编;
7,图形化工具:Depends来实现,可以查看一个可执行模块依赖的动态链接库;
8,除了使用extern关键字表明函数是外部定义的之外,还可以使用标识符:
_declspec(dllimport)来表明函数是从动态链接库中引入的。
而且这样编译器可以生成运行效率更高的代码。
9,在程序编译时,头文件不参与编译,源文件单独编译;
10,我们希望动态链接库文件在编译时,导出函数的名称不要发生改变。
为了实现这一目的,在定义导出函数时,需要加上限定符:extern “C”,注意双引号里面的C是大写;
但这样有一个缺陷:它可以解决C++和C语言之间相互调用时函数命名的问题,但是,就是不能导出一个类的成员函数,只能导出用于全局函数这种情况;
11,如果没有添加_stdcall关键字,那么函数调用约定就是C调用约定;
标准调用约定就是WINAPI调用约定,也就是pascal调用约定,这种调用方式与C调用约定不一样;
12,显示加载方式加载DLL:
LoadLibrary函数不仅能够加载DLL(.dll),还可以加载可执行模块(.exe)文件;
13,显示加载和隐式加载的区别:
如果采用隐式加载链接方式加载他们的话,那么在该程序启动时,这些DLL都需要被加载进到内存中,并映射到调用进程的地址空间,这样将加大程序的启动时间。
但一般来说,在程序运行过程中只是在某个条件满足时才需要访问某个DLL中的某个函数;
14,当采用动态方式加载DLL时,在客户端程序中将不能看到调用该DLL的输入信息了;
(即dumpbin imports选项没有用)
15.对于DLL来说,其入口函数是DLLMain
16.两者区别:
1. MFC扩展DLL:可以导出MFC类;
2. MFC常规DLL:不能导出MFC类,只能导出自己写的C++类;
17,如果采用动态加载方式使用DLL,在需要访问时,调用LoadLibary函数加载该DLL,当不再需要访问该DLL时,调用FreeLibrary函数释放对该DLL的引用;