|
DLL &
StaticLib BaseInfo (动态链接库与静态链接库基础知识) |
DLL 动态链接库
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。
动态链接与静态链接的不同之处在于:动态链接允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。
使用动态链接代替静态链接有若干优点。DLL 节省内存,减少交换操作,节省磁盘空间,更易于升级,提供售后支持,提供扩展 MFC 库类的机制,支持多语言程序,并使国际版本的创建轻松完成。[回到纲要]
动态链接具有下列优点:
·节省内存和减少交换操作。很多进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本。相反,对于每个用静态链接库生成的应用程序,Windows 必须在内存中加载库代码的一个副本。
·节省磁盘空间。许多应用程序可在磁盘上共享 DLL 的一个副本。相反,每个用静态链接库生成的应用程序均具有作为单独的副本链接到其可执行图像中的库代码。
·升级到 DLL 更为容易。当 DLL 中的函数发生更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相反,静态链接的对象代码要求在函数更改时重新链接应用程序。
·提供售后支持。例如,可修改显示器驱动程序 DLL 以支持当初交付应用程序时不可用的显示器。
·支持多语言程序。只要程序遵循函数的调用约定,用不同编程语言编写的程序就可以调用相同的 DLL 函数。程序与 DLL 函数在下列方面必须是兼容的:函数期望其参数被推送到堆栈上的顺序,是函数还是应用程序负责清理堆栈,以及寄存器中是否传递了任何参数。
·提供了扩展 MFC 库类的机制。可以从现有 MFC 类派生类,并将它们放到 MFC 扩展 DLL 中供 MFC 应用程序使用。
·使国际版本的创建轻松完成。通过将资源放到 DLL 中,创建应用程序的国际版本变得容易得多。可将用于应用程序的每个语言版本的字符串放到单独的 DLL 资源文件中,并使不同的语言版本加载合适的资源。
使用 DLL 的一个潜在缺点是应用程序不是独立的;它取决于是否存在单独的 DLL 模块。[回到纲要]
可执行文件以下列两种方式之一链接到(或加载)DLL:
隐式链接有时称为静态加载或加载时动态链接。显式链接有时称为动态加载或运行时动态链接。
在隐式链接下,使用 DLL 的可执行文件链接到该 DLL 的创建者所提供的导入库(.lib 文件)。使用 DLL 的可执行文件加载时,操作系统加载此 DLL。客户端可执行文件调用 DLL 的导出函数,就好像这些函数包含在可执行文件内一样。
在显式链接下,使用 DLL 的可执行文件必须进行函数调用以显式加载和卸载该 DLL,并访问该
DLL 的导出函数。客户端可执行文件必须通过函数指针调用导出函数。
可执行文件对两种链接方法可以使用同一个 DLL。另外,由于一个可执行文件可隐式链接到某个 DLL,而另一个可显式附加到此 DLL,故这些机制不是互斥的。[回到纲要]
为隐式链接到 DLL,可执行文件必须从 DLL 的提供程序获取下列各项:
·包含导出函数和/或 C++ 类的声明的头文件(.h 文件)。类、函数和数据均应具有
__declspec(dllimport)。
·要链接的导入库(.Lib files)。(生成 DLL 时链接器创建导入库。)
·实际的 DLL(.dll 文件)。
使用 DLL 的可执行文件必须包括头文件,此头文件包含每个源文件中的导出函数(或 C++ 类),而这些源文件包含对导出函数的调用。从编码的角度讲,导出函数的函数调用与任何其他函数调用一样。
若要生成调用可执行文件,必须与导入库链接。如果使用的是外部生成文件,请指定导入库的文件名,此导入库中列出了要链接到的其他对象 (.obj) 文件或库。
操作系统在加载调用可执行文件时,必须能够定位 DLL 文件。[回到纲要]
在显式链接下,应用程序必须进行函数调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:
·调用 LoadLibrary(或相似的函数)以加载 DLL 和获取模块句柄。
·调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引用,故无需与导入库链接。
·使用完 DLL 后调用
FreeLibrary。[回到纲要]
1.
从“文件”菜单中,选择“新建”,然后选择“项目…”。
2.
从“项目类型”窗格中,选择“Visual C++”下的“Win32”。
3.
从“模板”窗格中,选择“Win32 控制台应用程序”。
4.
为项目选择一个名称,如“MathFuncsLib”,并将其输入“名称”字段。为解决方案选择一个名称,如“StaticLibrary”,并将其输入“解决方案名称”字段。
5.
按“确定”启动 Win32 应用程序向导。在“Win32 应用程序向导”对话框的“概述”页中,按“下一步”。
6.
从“Win32 应用程序向导”的“应用程序设置”页中,选择“应用程序类型”下的“静态库”。
7.
从“Win32 应用程序向导”的“应用程序设置”页中,取消选择“附加选项”下的“预编译头”。
8.
按“完成”创建项目。[回到纲要]
1.
若要为新类创建头文件,请从“项目”菜单中选择“添加新项…”。将显示“添加新项”对话框。从“类别”窗格中,选择“Visual C++”下的“代码”。从“模板”窗格中选择“头文件(.h)”。为头文件选择一个名称,如“MathFuncsLib.h”,并按“添加”。将显示一个空白文件。
2.
添加一个名为“MyMathFuncs”的简单类,以执行常见的算术运算,如加、减、乘和除。代码应与以下内容类似:
//
MathFuncsLib.h
namespace
MathFuncs
{
class
MyMathFuncs
{
public:
//
Returns a + b
static
double Add(double a, double b);
//
Returns a - b
static
double Subtract(double a, double b);
//
Returns a * b
static
double Multiply(double a, double b);
//
Returns a / b
//
Throws DivideByZeroException if b is 0
static
double Divide(double a, double b);
};
}
3.
若要为新类创建源文件,请从“项目”菜单中选择“添加新项…”。将显示“添加新项”对话框。从“类别”窗格中,选择“Visual C++”下的“代码”。从“模板”窗格中,选择“C++ 文件(.cpp)”。为源文件选择一个名称,如“MathFuncsLib.cpp”,并按“添加”。将显示一个空白文件。
4.
在源文件中实现“MyMathFuncs”的功能。代码应与以下内容类似:
//
MathFuncsLib.cpp
//
compile with: /c /EHsc
//
post-build command: lib MathFuncsLib.obj
#include
"MathFuncsLib.h"
#include
<stdexcept>
using
namespace std;
namespace
MathFuncs
{
double MyMathFuncs::Add(double
a, double b) { return a + b; }
double
MyMathFuncs::Subtract(double a, double b) { return a - b; }
double
MyMathFuncs::Multiply(double a, double b) { return a * b; }
double
MyMathFuncs::Divide(double a, double b)
{
if
(b == 0)
{
throw new invalid_argument("b cannot
be zero!");
}
return a / b;
}
}
5.
若要将项目生成为静态库,请从“项目”菜单中选择“MathFuncsLib 属性…”。从左窗格中,选择“配置属性”下的“常规”。从右窗格中,将“配置类型”更改为“静态库(.lib)”。按“确定”保存更改。
6. 编译该静态库,方法是选择“生成”菜单中的“生成解决方案”。这将创建一个可供其他程序使用的静态库。[回到纲要]
1.
若要创建引用并使用刚刚创建的静态库的应用程序,请从“文件”菜单中选择“新建”,然后选择“项目…”。
2.
从“项目类型”窗格中,选择“Visual C++”下的“Win32”。
3.
从“模板”窗格中,选择“Win32 控制台应用程序”。
4.
为项目选择一个名称,如“MyExecRefsLib”,并将其输入“名称”字段。从“解决方案”旁边的下拉列表中选择“添入解决方案”。这会将新项目添加到该静态库所属的同一个解决方案中。
5.
按“确定”启动“Win32 应用程序向导”。在“Win32 应用程序向导”对话框的“概述”页中,按“下一步”。
6.
从“Win32 应用程序向导”的“应用程序设置”页中,选择“应用程序类型”下的“控制台应用程序”。
7.
从“Win32 应用程序向导”的“应用程序设置”页中,取消选择“附加选项”下的“预编译头”。
8.
按“完成”创建项目。[回到纲要]
调用静态库的程序与静态库版本间保持一致:
1、开发工具版本间一致;
2、Debug、Release版本间一致;
3、Unicode版本间一致;
4、调用VC运行时库(MSVCRTXX.dll)一致。[回到纲要]
Copyright@2004-2007 上海勇进软件有限公司,保留所有权利。
如果您对帮助系统有任何建议,可以直接发邮件到
Visual Studio,和Visual Studio logo 是微软公司在美国或在其他国家的注册商标。