现在的位置: 首页 > 综合 > 正文

静态链接库与动态链接库(中)

2013年01月10日 ⁄ 综合 ⁄ 共 1772字 ⁄ 字号 评论关闭

五、认识动态链接库

动态链接是相对于静态链接而言的。所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。换句话说,函数和过程的代码就在程序的exe文件中,该文件包含了运行时所需的全部代码。当多个程序都调用相同函数时,内存中就会存在这个函数的多个拷贝,这样就浪费了宝贵的内存资源。而动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)。仅当应用程序被装入内存开始运行时,在Windows的管理下,才在应用程序与相应的DLL之间建立链接关系。当要执行所调用DLL中的函数时,根据链接产生的重定位信息,Windows才转去执行DLL中相应的函数代码。一般情况下,如果一个应用程序使用了动态链接库,Win32系统保证内存中只有DLL的一份复制品

动态链接库的两种链接方法:

(1) 装载时动态链接(Load-time Dynamic Linking):这种用法的前提是在编译之前已经明确知道要调用DLL中的哪几个函数,编译时在目标文件中只保留必要的链接信息,而不含DLL函数的代码;当程序执行时,利用链接信息加载DLL函数代码并在内存中将其链接入调用程序的执行空间中,其主要目的是便于代码共享。

(2) 运行时动态链接(Run-time Dynamic Linking):这种方式是指在编译之前并不知道将会调用哪些DLL函数,完全是在运行过程中根据需要决定应调用哪个函数,并用LoadLibrary和GetProcAddress动态获得DLL函数的入口地址。

六、制作一个简单的DLL

第4节给出了以静态链接库方式提供add函数接口的方法,接下来我们来看看怎样用动态链接库实现一个同样功能的add函数。

如图 3,在VC 中new一个Win32 Dynamic-Link Library工程dllTest。注意不要选择MFC AppWizard(dll),因为这两只方式创建出来的动态库格式不一样。

在建立的工程中添加lib.h及lib.cpp文件,源代码如下:

/* 文件名:lib.h*/

#ifndef LIB_H

#define LIB_H

extern "C" int __declspec(dllexport) add(int x, int y);

#endif

/* 文件名:lib.cpp*/

#include "lib.h"

int add(int x, int y)

{

return x y;

}

最后点击Build按钮(或菜单项Build> Build dllTest.dll)。创建成功之后在工程所在子目录的Debug子目录下就可以找到dllTest.dll文件。另外我们还可以看到一个dllTest.lib文件,后面我们解释该文件的作用。

分析上述代码,dllTest工程中的lib.cpp文件与第2节静态链接库版本完全相同,不同在于lib.h对函数add的声明前面添加了__declspec(dllexport)语句。这个语句的含义是声明函数add为DLL的导出函数。DLL内的函数分为两种:

(1) DLL导出函数,可供应用程序调用;

(2) DLL内部函数,只能在DLL程序使用,其他应用程序无法调用它们。

DLL中导出函数的声明有两种方式:一种为上面例子中给出的在函数声明中加上__declspec(dllexport),这里不再举例说明;另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。

下面的代码演示了怎样同.def文件将函数add声明为DLL导出函数(需在dllTest工程中添加lib.def文件):

; lib.def : 导出DLL函数

LIBRARY dllTest

EXPORTS

add @ 1

.def文件的规则为:

(1) LIBRARY语句说明.def文件相应的DLL;

(2) EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

(3) .def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。

由此可以看出,例子中lib.def文件的含义为生成名为“dllTest”的动态链接库,导出其中的add函数,并指定add函数的序号为1。

抱歉!评论已关闭.