日常使用MFC开发动态链接库的时候,你可能会面临“MFC的使用”这个选项,这个选项里面有三种可选方案,分别是:
-
使用标准 Windows 库
-
在静态库中使用 MFC
-
在共享 DLL 中使用 MFC
那么这三种有什么区别呢?为什么要设置这三种方式呢?
根据小编在开发项目过程中所遇到的问题,按照自己的理解给大家揭开这三者的区别。
我们都知道,动态库是什么东西,不懂得小伙伴可以看小编之前整理的动态链接库文章,动态链接库通常不能直接在操作系统上运行,他在我们的电脑上呈现的后缀名为 .dll,同时它也不能接收消息。它是一个独立的文件,只有在某一个可执行文件(windows上是.exe)来调用才能够生效。众所周知,Windows API中所有的函数都包含在DLL中,其中有3个最为重要的DLL就是:
-
Kernel32.dll:包含用于管理内存、进程和线程的函数,例如CreateThread函数;
-
User32.dll:包含用于执行用户界面任务(如窗口的创建和消息的传递)的函数,例如CreateWindow函数;
-
GDI32.dll:包含用于画图和显示文本的函数。
当我们在创建MFC工程的时候,选择创建动态链接库工程,编译出来后会在生成库的文件路径下多生成一个引入库文件,这个引入库文件的后缀名也是“lib”,例如下图中的Serven.lib文件:
但是,动态链接库的引入库文件和静态库文件有着本质的区别,对一个DLL来说,其引入库文件包含该DLL导出的函数和变量的符号名,而DLL文件包含该DLL实际的函数和数据。在使用动态库的情况下,在编译链接可执行文件时,只需要链接该DLL的引入库文件,该DLL中的函数代码和数据并不复制到可执行文件中,直到可执行文件运行时,采取加载所需的DLL,将该DLL映射到进程的地址空间中,然后访问DLL中导出的函数。这时,在发布产品时,出了发布可执行文件外,还需要发布该程序要调用的动态链接库,如下图所示,假设我们的可执行程序为Servenexe.exe,DLL库文件为Serven.dll,在发布的时候将这两个文件打包成一个文件夹一起发布。
说了这么多,我们来看一下“使用共享动态MFC DLL的规则(D)”和“带有静态链接MFC的规则”。
使用共享动态MFC DLL的规则(D):
编译器在编译的时候,不会把MFC的库函数给编译进来,也就是,当我们在DLL程序中使用了MFC的库函数(例如CreateWindows()),编译器不会把这个函数编译进来,所以这个要求要运行这个dll文件的电脑上必须安装过MFC库函数,也就是安装MFC的环境。如果电脑上没有安装的话,那么就会出现下面这个报错:
提示你没有,程序没有找到相应的MFC库函数。使用这种方式的缺点就是要求运行该库的电脑上必须安装相应的MFC库函数。
使用“带有静态链接MFC的规则”的方式:
编译器在编译的时候,会把MFC的库函数给编译进来,也就是,当我们在DLL程序中使用了MFC的库函数(例如CreateWindows()),编译器会把这个函数编译进来,所以这个不要求要运行这个dll文件的电脑上必须安装过MFC库函数,也就是安装MFC的环境。但是这个有一个缺点就是编译后的dll的大小会比使用共享动态的方式要大。
总结:
-
使用标准Windows库:只能用在非MFC工程中,如果在MFC工程会导致代码编译报错;
-
在共享DLL中使用MFC:生成的程序可执行文件比较小,但是要求目标机器上必须安装必要的MFC库文件;
-
在静态库中使用MFC:生成的程序可执行文件几乎所有的Windows都可以执行,但是这个程序生成后占用的内存会比较大,因为程序包含了必要的MFC库文件,可以保证在别的机器上正常运行。