1.前言:
人总归还是要有梦想的,不然跟咸鱼有什么区别。这一周给自己定下了研究DLL的任务还是要逼自己完成的呀,上了一天的党校,游戏也不打在这里写博,心疼自己。话说为什么要给自己下这样一个任务呢,是因为在研究数据库编程的过程中看到了书上写着相关DLL的编写问题,感觉也挺有意思的,不妨先来研究一下DLL。
2.DLL概论:
DLL(Dynamic Link Library):DLL文件中存放的是各类程序的函数(子过程)实现过程,当程序需要调用函数时需要先载入DLL,然后取得函数的地址,最后进行调用。(以上摘自百度百科.意义)
按照我的理解,引用一个DLL就好似 #include 了某一个.h文件,其中有许多我们待用的函数或者变量或者类等可以供我们调用。 而在DLL发展的过程中经历了“无库-静态链接库-动态链接库”的时代。(.h文件只是一个类比..有些不太准确,因为大部分.h文件之中只有函数或理解为申明,并没有实现函数的具体过程)
3.使用DLL给编程带来的好处:
随着软件业的不断发展,程序员需要面对的大型、超大型的项目越来越多。使用DLL可以大大方便这些超大型项目的开发工作,简化项目管理。
比如我们可以按照功能将一个大型项目分解成多个部分,把参加整个项目的人员也分成多个项目组,然后让每个项目组完成其中的一部分功能,多项目组同时开发,完成各个功能之后我们只需要将这些DLL链接起来即可。这样做可以有效加快软件编写的进度。
DLL的编写与具体的编程语言以及编辑器没有关系,只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。譬如使用Visual C++编写的DLL,在任何开发环境中都能被调用,不在乎其是Visual Basic、Delphi或者其他的开发环境。
DLL还有一个非常好的特点就是它有助于共享数据和资源。如果多个应用程序需要访问同一个功能,我们可以先将实现该功能的函数写到一个DLL中,这样机器上只需要有一份该DLL就可以了,所有需要该功能的应用程序只需链接该DLL即可调用其中的函数,这样就节省了磁盘空间。在使用时,如果多个应用程序需要同时使用该DLL,那么只需要将该DLL读入内存一次,所有需要使用该DLL的应用程序就可以共享该DLL所在内存页面,从而达到节省内存的目的。
(以上内容摘自Visual C++程序设计与项目实践.安金梁 238页)
4.静态链接库:
静态链接库在编写时函数和数据被编译进一个二进制文件(通常扩展名为.lib),在被主程序使用时,链接接器从静态链接库中复制其中的函数和数据并把它们和主程序一起创建可执行文件(通常,其扩展名为.exe)。所以,静态链接库是在链接时被链接到EXE文件中的,静态链接库本身不需要与可执行文件一起发行,这一点和动态链接库不同。
通过了解,貌似现在开发软件都不怎么经常使用静态链接库了,所以就用Visual C++6.0来做一个示范:
(1)在Visual C++6.0 中新建一个名为“StaticLibTest”的静态链接库程序:
(2)把这两个选项勾选上:
注:√预编译的头文件 - 生成了默认的这些文件,StdAfx的意思是 Standard Application Frame Extend。StdAfx没有函数库,只是定义了一些参数,使得编译出来的程序能在相应的环境下运行。
√MFC支持 - 是想用MFC集成的诸如 AfxMessageBox 这样的函数来反馈信息。
(3)分别添加 “StaticLibTest.cpp” 源文件和 “StatciLibTest.h” 头文件到工程中并添加以下代码:
// 头文件 StaticLibTest.h 中的代码: #ifndef __STATIC_LIB_H__ #define __STATIC_LIB_H__ extern "C" void StaFunc(); #endif
// 源文件 StaticLibTest.cpp 中的代码: #include "StdAfx.h" #include "StaticLibTest.h" void StaFunc() { AfxMessageBox("成功调用静态链接库中的函数!"); }
按下快捷键F7,工程 StaticLibTest 就会在目录下生成对应的静态链接库文件 StaticLibTest.lib。该文件位于“Debug”或“Release”目录中。
前面已经交代过,静态链接库和动态链接库是不能直接被运行的,必须通过其他程序的调用,所以我们再来写一个 MFC 基本对话框应用程序 MasterProgram 来调用静态链接库之中的函数。
(4)关闭之前的工作空间,新建一个 MFC 基本对话框应用程序 MasterProgram:
之后直接点击完成就好,用默认参数。
(5)双击OK按钮,添加如下代码:
void CMasterProgramDlg::OnOK() { // TODO: Add extra validation here StaFunc(); // 调用静态链接库中的函数 CDialog::OnOK(); }
(6)把静态链接库的相关文件拷贝到 MasterProgram 程序的根目录下并在 MasterProgramDlg.h 中添加代码将其与静态链接库中链接在一起:
拷贝到工程的根目录下然后加入以下代码:
#include "StaticLibTest.h" #pragma comment(lib,"staticLibTest.lib")
(7)编译并验证:
完美。
5.动态链接库的编写方法
用VC++创建的动态链接库通常包含两个文件,一个 .lib 格式的文件和一个 .dll 格式的文件。这个 .lib 格式的文件称为引入库文件,与静态链接库中的 .lib 文件不同。引入库文件包含 DLL 到处的函数和变量的符号名,动态链接库中的实际函数和数据则包含在 .dll 文件格式的文件中。在主程序使用隐式加载方式链接动态链接库时,只需将动态链接库的引入库文件与主程序进行链接即可,而动态链接库中的函数代码和数据并不复制到可执行文件中,只有在可执行程序运行时,主程序才去加载所需要的额动态链接库,将该 DLL 映射到地址空间中,然后访问 DLL 中到处的函数和数据。所以,在发布主程序时,除了发布.exe 格式的可执行文件还需要同时发布主程序需要调用的.dll 格式的文件。
在这里我就只简单的讨论一下 MFC DLL 的调用问题吧:(个人感觉显示加载才是写项目的王道,所以就只测试一下显示加载的方法)
(1)在 Visual C++ 6.0 中新建一个名为 “MFCDLL”的 MFC DLL 程序:
(2)点击 OK 按钮,然后进入“MFC 应用程序向导” 对话框:
这里出现了几个选项可以说明一下:
● 动态链接库和 MFC 静态链接库:
使用 MFC 静态链接库的常规 DLL 在发布时只需提供我们编写的 DLL ,而且在有 MFC 类库的机器上生成之后,就可以在没有 MFC 类库的机器上使用了。
● 动态链接库使用共享 MFC DLL:
使用这个方法创建的 DLL 比上面的一种方法创建的文件要小上一些,占用的磁盘空间和内存空间都会小。但是此方法不能在没有 MFC 类库的机器上不能使用。
● MFC 扩展 DLL 使用共享:
MFC 扩展 DLL 也使用共享MFC,所以在没有 MFC 的机器上无法使用。
“扩展 DLL”和“常规 DLL”的区别是牵着还能导出 MFC 类。
● 自动:(自动化)
选择是否支持自动化技术,自动化技术允许用户在一个应用程序中操纵另外一个应用程序或组件。例如,我们可以在应用程序中利用 Microsoft Word 或 Microsoft Excel 提供的工具,而这种使用对用户而言是透明的。
● 套接字:(Windows Sockets)
选择是否支持 Windows Sockets ,选择此项目应用程序将会自动添加一些能在 TCP/IP 网络上进行通信的功能。
这里就按图这样选择好了,其他都默认,直接按完成点击 OK 创建默认工程。
(3)类似于静态链接库那样的,建立一个“MFCDLLOutPut.h” 的头文件和“MFCDLLOutPut.cpp” 的源文件并添加代码:
// MFCDLLOutPut.h 中的代码: #ifndef __MFCDLL__FUNCTION__DEFINE__H__ #define __MFCDLL__FUNCTION__DEFINE__H__ void MFCfunc() { AfxMessageBox("MFCDLL调用成功!");7 #endif
注:还没有完成这个,先发表吧...