论文部分内容阅读
摘 要:介绍了Windows下动态链接库的创建和使用方法。
关键词:动态链接库 导出函数 隐式链接 显式链接
中图分类号 TF311.52 文献标识码 B 文章编号:1002-2422(2007)03--0048-02
1 动态链接库的创建
在VC 6.0开发系统的菜单“File”中单击“New”,在弹出窗口中选择Project选项卡,可以看到有Win32 Dy-name-Link Library和MFC AppWizard两种方式创建动态链接库。前者用来创建不与MFC(微软基础类库)链接的动态链接库,称为非MFC动态库,后者创建与MFC链接的动态链接库,称为MFC动态库。
1.1 创建非MFC动态库
选择Win32 Dynamic-Link Library,在Project name编辑框输入工程名:MyDLL,创建一个空的非MFC工程。
要使DLL中包含的某些函数和数据能够被外部应用程序调用,就应该在创建DLL时,指出这些函数(数据)是可导出的,称为导出函数(数据)。导出函数有两种方法,一种是在声明函数原型语句中的函数类型关键字左边添加导出关键字_declspec(dlhxport);另一种是使用模块定义文件.def。
(1)使用导出关键字declapee(duexport)导出函数
在前面创建的空工程中加入MyDLL.h、MyDL、cpp两个文件,
头文件MyDLL.h.代码如下:_declspec(dllexport)int Add(int x,int y);
实现文件MyDLL.cpp代码如下:#include
#include“MyDLL.h”
int Add(int x,int y)
{ return(x+y);}
在工程中有一个被导出函数(输出函数)Add(),用来进行加法运算。
编译、连接工程MyDLL,成功后,可以看到debug目录下生成了动态库MyDLL.d11和引入库MyDLL.Iib这两个文件。引入库文件中存有对应DLL的文件名和输出函数名等(MyDLL、Add等),动态库文件中存有实际的函数和数据。
(2)使用模块定义文件.def导出函数
对方法(1)中建立的工程,删除文件MyDLL.h,保留文件MyDLL.cpp,再加入文本文件MyDLL.def作为模块定义文件。在MyDLL.def中输入代码如下:
;MyDLL.def
LIBRARY MyDLL
EXPORTS
Add
一个模块定义文件至少要有两条语句,一条是LI-BRARY语句,用它指出DLL的名字,该语句必须位于除注释语句外的其它语句之前;另一条是EXPORTS语句,在它之下列出输出函数的名字。
1.2 创建MFC动态库
选择MFC AppWizard,在Project name编辑框输入工程名:MyDLL,单击OK,可创建三种类型的MFC动态库:第一种是与MFC静态链接的常规DLL(Regular DLLWith MFG Statically Linked);第二种是与MFC动态链接的常规DLL(Regular DLL using shared MFC DLL)。常规DLL既可以被MFC应用程序使用,也可以被非MFC应用程序使用(BC,VB等)。第三种是MFC扩展型DLL(MFCExtension DLL),这种DLL与MFC动态链接,其特点是可导出MFC派生类,但MFC扩展型DLL只能被那些动态链接到MFC的应用程序使用。
MFC动态库导出函数(或变量)的方法与非MFC动态库的导出方法相同。
MFC扩展DLL导出类的常用方法是在类的声明前加一个宏“AFX_EXT_CLASS”,例如:class AFX_EXT_CLASSCMyClass;
特别要注意的是,对于动态链接到MFC的DLL,其输出函数若要调用MFC,则在该输出函数的定义体内第一条语句必须是下面的宏语句:
AEX_MANAGE_STATE(AfxCetStaticModuleStme());
此语句保证在其后输出函数中的语句能够调用MFC。
新创建的动态链接库提供给其它程序使用时(或发布)要提供三个文件:动态库文件(MyDLLdll)、引入库文件(MyDLL.lib)和头文件(MyDLL.h)。发布与MFC动态链接的动态库时还要附上VC 开发系统内的MFC#O.dll(文件名中#是MFC的版本号码)和MSVCRT.dll这两个动态库。
2 动态链接库的使用
应用程序使用动态库时可以采用两种链接方式:隐式链接和显式链接。
2.1 隐式链接
应用程序使用引入库(.lib)文件隐式链接到DLL,DLL中的函数和数据并不复制到可执行文件中,在可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址。隐式链接方式下,操作系统加载应用程序时就加载DLL文件。
实现隐式链接需要创建动态库时产生的三个文件:动态库文件(.dll)、引入库文件(.lib)和头文件(.h)。隐式链接的三个要点如下:
(1)把动态库的头文件(.h)拷贝到应用程序工程目录下,对其拷贝作如下修改:把所有的导出关键字declspec(dllexport)换成导入关键字_declspec(dllimport),在文件开始处加入语句:#pragma comment(lib,“引入库名”),告诉Link要连接引入库,在应用程序的各个使用DDL的.cpp文件中用语句#include包含这个头文件(.h)。
(2)将引入库(.lib)拷贝到应用程序工程目录下,以便VC 的Link链接时使用。
(3)将动态库(.dll)复制到应用程序工程目录下,便于Windows查找。
下面是一个制台应用程序DLLTestA隐式链接到前面创建的动态库的例子。
头文件DLLTestA.h代码如下:
#pragma comment(lib,“MyDLL.lib”)
_declspec(dllimport)int Add(int x,int y);
实现文件DLLTestA.cpp代码如下:
#1nchde
#include“DLLTestA.h”
void main()
{int a;
a=Add(20,10);
printf(“20 10=%d”,a);
}
DLLTextA.h文件中的关键字pmgam comment通知Link程序要链接MyDLL.lib。导入关键字_declspec(dl-Hmpoa)用来说明其后的函数是从动态库中引入的。按Ctrl F5键就可以编译执行该程序。
2.2 显式链接
使用显式链接时,应用程序不需要使用相应的.lib和.h文件,只需将.dll拷贝到当前工作目录下即可。显式链接方式下,应用程序运行时可以随时加载和卸载DLL。
显式链接的几个要点如下:
(1)调用GetModuleHandle()函数检查DLL是否已经被映射到进程的地址空间中:
(2)调用LoadLibrary函数加载DLL并得到其模块句柄:
(3)调用GetProcAddress函数获得DLL中输出函数的地址:
(4)使用DLL结束后,调用FreeLibrary函数卸载DLL。
下面是在MFC对话框工程DLLTestB中实现显式链接的部分代码:
void CDLLTestBDlg::OnAdd()
{
HMODULE hlnst=GetModuleHandle(“MyDLL.dll”);
if(hlnst==NULL)
{hlnst=LoadLibrary(“MyDLL.dll”);}
typcda int(*AddProe)(int m,int n);
AddProc addp=(AddProc)GetProcAddress(hlnst“Add”);
if(!addp){“MessageBox(“获取函数地址失败!”);return;”}
CString str;
str.Format(“10 20=%d”,addp(10,20));
MessageBox(str);
FreeLibrary(hlnst);
}
上面代码中使用类型定义关键字typedef定义与DLL中相同类型的函数指针,用来存函数的地址。
3 结束语
DLL封装了共享资源和代码,在开发以Windows为平台的应用程序时,使用DLL技术开发项目,可简化项目管理,提高开发速度。因此,掌握DLL技术很有必要。
关键词:动态链接库 导出函数 隐式链接 显式链接
中图分类号 TF311.52 文献标识码 B 文章编号:1002-2422(2007)03--0048-02
1 动态链接库的创建
在VC 6.0开发系统的菜单“File”中单击“New”,在弹出窗口中选择Project选项卡,可以看到有Win32 Dy-name-Link Library和MFC AppWizard两种方式创建动态链接库。前者用来创建不与MFC(微软基础类库)链接的动态链接库,称为非MFC动态库,后者创建与MFC链接的动态链接库,称为MFC动态库。
1.1 创建非MFC动态库
选择Win32 Dynamic-Link Library,在Project name编辑框输入工程名:MyDLL,创建一个空的非MFC工程。
要使DLL中包含的某些函数和数据能够被外部应用程序调用,就应该在创建DLL时,指出这些函数(数据)是可导出的,称为导出函数(数据)。导出函数有两种方法,一种是在声明函数原型语句中的函数类型关键字左边添加导出关键字_declspec(dlhxport);另一种是使用模块定义文件.def。
(1)使用导出关键字declapee(duexport)导出函数
在前面创建的空工程中加入MyDLL.h、MyDL、cpp两个文件,
头文件MyDLL.h.代码如下:_declspec(dllexport)int Add(int x,int y);
实现文件MyDLL.cpp代码如下:#include
#include“MyDLL.h”
int Add(int x,int y)
{ return(x+y);}
在工程中有一个被导出函数(输出函数)Add(),用来进行加法运算。
编译、连接工程MyDLL,成功后,可以看到debug目录下生成了动态库MyDLL.d11和引入库MyDLL.Iib这两个文件。引入库文件中存有对应DLL的文件名和输出函数名等(MyDLL、Add等),动态库文件中存有实际的函数和数据。
(2)使用模块定义文件.def导出函数
对方法(1)中建立的工程,删除文件MyDLL.h,保留文件MyDLL.cpp,再加入文本文件MyDLL.def作为模块定义文件。在MyDLL.def中输入代码如下:
;MyDLL.def
LIBRARY MyDLL
EXPORTS
Add
一个模块定义文件至少要有两条语句,一条是LI-BRARY语句,用它指出DLL的名字,该语句必须位于除注释语句外的其它语句之前;另一条是EXPORTS语句,在它之下列出输出函数的名字。
1.2 创建MFC动态库
选择MFC AppWizard,在Project name编辑框输入工程名:MyDLL,单击OK,可创建三种类型的MFC动态库:第一种是与MFC静态链接的常规DLL(Regular DLLWith MFG Statically Linked);第二种是与MFC动态链接的常规DLL(Regular DLL using shared MFC DLL)。常规DLL既可以被MFC应用程序使用,也可以被非MFC应用程序使用(BC,VB等)。第三种是MFC扩展型DLL(MFCExtension DLL),这种DLL与MFC动态链接,其特点是可导出MFC派生类,但MFC扩展型DLL只能被那些动态链接到MFC的应用程序使用。
MFC动态库导出函数(或变量)的方法与非MFC动态库的导出方法相同。
MFC扩展DLL导出类的常用方法是在类的声明前加一个宏“AFX_EXT_CLASS”,例如:class AFX_EXT_CLASSCMyClass;
特别要注意的是,对于动态链接到MFC的DLL,其输出函数若要调用MFC,则在该输出函数的定义体内第一条语句必须是下面的宏语句:
AEX_MANAGE_STATE(AfxCetStaticModuleStme());
此语句保证在其后输出函数中的语句能够调用MFC。
新创建的动态链接库提供给其它程序使用时(或发布)要提供三个文件:动态库文件(MyDLLdll)、引入库文件(MyDLL.lib)和头文件(MyDLL.h)。发布与MFC动态链接的动态库时还要附上VC 开发系统内的MFC#O.dll(文件名中#是MFC的版本号码)和MSVCRT.dll这两个动态库。
2 动态链接库的使用
应用程序使用动态库时可以采用两种链接方式:隐式链接和显式链接。
2.1 隐式链接
应用程序使用引入库(.lib)文件隐式链接到DLL,DLL中的函数和数据并不复制到可执行文件中,在可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址。隐式链接方式下,操作系统加载应用程序时就加载DLL文件。
实现隐式链接需要创建动态库时产生的三个文件:动态库文件(.dll)、引入库文件(.lib)和头文件(.h)。隐式链接的三个要点如下:
(1)把动态库的头文件(.h)拷贝到应用程序工程目录下,对其拷贝作如下修改:把所有的导出关键字declspec(dllexport)换成导入关键字_declspec(dllimport),在文件开始处加入语句:#pragma comment(lib,“引入库名”),告诉Link要连接引入库,在应用程序的各个使用DDL的.cpp文件中用语句#include包含这个头文件(.h)。
(2)将引入库(.lib)拷贝到应用程序工程目录下,以便VC 的Link链接时使用。
(3)将动态库(.dll)复制到应用程序工程目录下,便于Windows查找。
下面是一个制台应用程序DLLTestA隐式链接到前面创建的动态库的例子。
头文件DLLTestA.h代码如下:
#pragma comment(lib,“MyDLL.lib”)
_declspec(dllimport)int Add(int x,int y);
实现文件DLLTestA.cpp代码如下:
#1nchde
#include“DLLTestA.h”
void main()
{int a;
a=Add(20,10);
printf(“20 10=%d”,a);
}
DLLTextA.h文件中的关键字pmgam comment通知Link程序要链接MyDLL.lib。导入关键字_declspec(dl-Hmpoa)用来说明其后的函数是从动态库中引入的。按Ctrl F5键就可以编译执行该程序。
2.2 显式链接
使用显式链接时,应用程序不需要使用相应的.lib和.h文件,只需将.dll拷贝到当前工作目录下即可。显式链接方式下,应用程序运行时可以随时加载和卸载DLL。
显式链接的几个要点如下:
(1)调用GetModuleHandle()函数检查DLL是否已经被映射到进程的地址空间中:
(2)调用LoadLibrary函数加载DLL并得到其模块句柄:
(3)调用GetProcAddress函数获得DLL中输出函数的地址:
(4)使用DLL结束后,调用FreeLibrary函数卸载DLL。
下面是在MFC对话框工程DLLTestB中实现显式链接的部分代码:
void CDLLTestBDlg::OnAdd()
{
HMODULE hlnst=GetModuleHandle(“MyDLL.dll”);
if(hlnst==NULL)
{hlnst=LoadLibrary(“MyDLL.dll”);}
typcda int(*AddProe)(int m,int n);
AddProc addp=(AddProc)GetProcAddress(hlnst“Add”);
if(!addp){“MessageBox(“获取函数地址失败!”);return;”}
CString str;
str.Format(“10 20=%d”,addp(10,20));
MessageBox(str);
FreeLibrary(hlnst);
}
上面代码中使用类型定义关键字typedef定义与DLL中相同类型的函数指针,用来存函数的地址。
3 结束语
DLL封装了共享资源和代码,在开发以Windows为平台的应用程序时,使用DLL技术开发项目,可简化项目管理,提高开发速度。因此,掌握DLL技术很有必要。