Dynamic-Link Libraries(DLLS)在MFC Visual C++ 6中的使用问题

发表于:2007-07-01来源:作者:点击数: 标签:
动态链接库(DLL)由可执行模块组成,为进程提供数据、代码和资源。编译时使用的静态链接库不同的是,动态链接库独立于激活它们的可执行文件,调用的地址转换是在加载 时解决的。这使DLL的故障查找和小的修改比较简单,不必重新编译调用它们的可执行模块。 V


   动态链接库(DLL)由可执行模块组成,为进程提供数据、代码和资源。编译时使用的静态链接库不同的是,动态链接库独立于激活它们的可执行文件,调用的地址转换是在加载 时解决的。这使DLL的故障查找和小的修改比较简单,不必重新编译调用它们的可执行模块。
Visual Studio提供AppWizard生成MFC DLL。给出名字和目录信息后,AppWizard还要求一个关键信息:DLL类型。可选的类型包括:MFC DLL静态链接的常规DLL(Regular DLL with MFC statically linked),使用共享MFC DLL的常规DLL(Regular DLL using shared MFC DLL)和MFC扩充DLL(MFC Extension DLL(using shared MFC DLL))。因此,常把MFC DLL基本上分成两个类型:
.常规DLL 可能包含MFC类,但导出不使用MFC派生类的函数。常规DLL可以链接MFC和C运行时间静态库或动态库。
.MFC扩充DLL 包含从MFC类派生的可公共访问的类的DLL,被称为AFX扩充DLL或AFX DLL。AFC DLL是唯一可发布MFC派生类供其它DLL或可执行模块用的DLL。扩充DLL以及使用它们的模块需要与MFC库的DLL版本链接,实际上,也要求与C运行库的DLL版本链接。扩充DLL通过与MFC库的DLL版本的链接,可以导出窗口类、消息映射和动态(可串行化的)对象。
本文就MFC DLL编写及使用中的部分问题,结合个人开发程序的经验与体会,作几点说明。
一、开发和使用DLL需注意三种文件
1、 DLL头文件(.H)
它是指DLL中说明输出的类或符号(Symbols)原型或数据结构的.H文件。当其它应用程序调用DLL时,需要将该文件包含入应用程序的源文件中。
2、 DLL的引入库文件(.LIB)
它是DLL在编译、链接成功后生成的文件。主要作用是当其它应用程序调用DLL时,需要将该文件引入应用程序。否则,DLL无法引入。
3、 DLL文件(.DLL)
它是应用程序调用DLL运行时,真正的可执行文件。DLL应用在编译、链接成功后,.DLL文件即存在。开发成功后的应用程序在发布时,只需要有.EXE文件和.DLL文件,不必有.LIB文件和DLL头文件。
二、导出与导入
为使类和函数外部可见,被其它扩充DLL和可执行模块所使用,必须导出它们,告诉编译器和链接程序函数可供外部使用,并提供一个识别符用来访问它们。这些识别符归入由链接程序创建的导入库。使用扩充DLL的模块必须与导入库链接。
对于常规DLL来说,输出函数一般分三步:
1) 说明输出函数原型
一般在常规DLL的头文件(.H)中定义。如:
//StaticDLLAPI.h
extern “C”
void FAR PASCAL EXPORT PopupStaticDLG();//其中PopupStaticDLG()为输出函数
2) 编写输出函数代码
一般在常规DLL的源文件中实现输出函数的功能。如:
//StaticDLL.cpp
#include “StaticDLLAPI.h”
extern“C”
void FAR PASCAL EXPORT PopupStaticDLG()
{
……
}
3) 在.DEF文件中输出函数
如:
EXPORTS
PopupStaticDLG @2
对于MFC扩充DLL来说,导出类、函数和数据,以及导入问题,稍复杂一些,下面就部分关键问题加以说明。
首先,导出一个识别符的关键字是_declspec(dllexport),导入一个识别符的关键字是_declspec(dllimport)。声明规范告诉编译器如何生成此函数的进入退出代码,如何调用此函数。
其次,MFC导出策略是复杂的,且经高度优化的。可以通过两种方法导出符号:一种方法是通过名字导出。由于整个函数名必须出现在可执行文件中,而使用DLL的每个可执行文件必须包含所用符号的名字,并且解析每个符号需要对每个导出名字逐个字符地进行比较,因此存在严重的性能问题。另一种方法是通过赋一个数值(序号)给链接程序来导出符号。序值对DLL必须是唯一的。使用序号时,DLL的导入库含有名字和序号,但可执行文件和模块定义文件(DEF)只含序值。与基于名字的导出不同,符号解析只是一次快速的整数查找过程。
第三,导出类、MFC数据,以及函数,包括显函数、析构函数、虚拟函数等,具体操作可查相关资料,此处不再详述。
三、编译及链接
MFC DLL编写完成后,必须经过编译和链接之后,才能被引用。因此,编译和链接是DLL使用中的一个重要环节。
下面就编译和链接过程中的重要设置问题加以阐述。
4、 文件路径调整
选择Tools菜单下Options…选项,打开Options对话框中的Directories页面。在Directories编辑框中添加主文件项目目录路径和DLL库文件项目目录路径。注意Platform设置为Win32,Show directories for设置为Include files。
5、 工程编译选项调整
选择Project菜单下Settings…,打开Project Settings对话框,分别对以下几个页框进行设置。
1)General页
Setting For设置为Win32 Debug。可以看到左边的编辑框中列出了主文件项目和库文件项目,分别对它们的临时文件(如.OBJ等)和输出文件(如.LIB,.DLL等)路径进行设置。2)Debug页
只需对主文件项目的工作路径(Working directory),及执行文件路径(Executable for debug session)进行设置即可。3)Link页
其它基本设置不变。但在Output file name编辑框中,应分别指明库文件项目的DLL文件(.DLL)路径,以及主文件项目的执行文件(.EXE)路径;在Object/Library modules编辑框中,应对主文件项目指明调用库文件项目的库文件(.LIB)路径。四、小结
至此,本文简要地阐述了MFC DLL使用中的一些关键问题,均来自个人程序开发的经验与体会,希望能对广编程爱好者有所帮助。当然,DLL的内容还相当丰富,我们还将继续不断地学习。


原文转自:http://www.ltesting.net