动态链接库在存储管理中的应用效果如何?
- 行业动态
- 2025-01-24
- 3828
存储管理之动态链接库实验报告
一、实验目的
1、理解动态链接库的实现原理,包括其在程序运行中的作用和优势。
2、掌握 Windows 系统下动态链接库的建立方法,能够创建并编译自己的动态链接库文件。
3、掌握 Windows 环境下动态链接库的调用方法,包括静态调用和动态调用两种方式。
二、实验准备知识
1、动态链接库介绍:动态链接库(Dynamic Link Library,DLL)是一个可执行模块,包含的函数可由 Windows 应用程序调用以提供所需功能,其优点包括减少应用程序大小、节省内存资源以及便于多个应用程序共享代码等,在 Windows 系统中,DLL 文件扩展名为 .dll,运行时被加载到进程的虚拟地址空间中。
2、动态链接库入口函数:DllMain() 函数是动态链接库的入口函数,当 Windows 系统加载或卸载动态链接库时调用该函数,它主要用于进行一些初始化和清理工作,如分配或释放资源等。
3、动态链接库导入 / 导出函数:动态链接库文件中包含一个导出函数表,表中有函数的符号名和标识名等信息,当应用程序加载动态链接库时,通过这些信息找到函数的地址,如果重新编译动态链接库文件,只要不改变导出函数的符号名和参数,就无需修改调用它的应用程序。
4、动态链接库的两种链接方式:隐式链接和显式链接,隐式链接是在应用程序源代码中只引用动态链接库中的符号,运行时加载程序自动将动态链接库装入进程地址空间;显式链接则是在应用程序运行时使用 LoadLibrary() 函数显式地加载动态链接库,并使用 GetProcAddress() 函数获取函数地址。
1、建立动态链接库工程:在 Microsoft Visual C++ 6.0 环境下,选择 File->New 命令,在 Project 选项卡中选择 Win32 Dynamic-Link Library 建立动态链接库工程文件,输入工程文件名和选择工程文件所在路径后点击确定按钮。
2、编写动态链接库代码:定位到生成的 .h 文件处,添加动态链接库的函数原型声明,创建一个实现两个整数相加和相乘的动态链接库,可在 .h 文件中添加如下代码:
extern "C" __declspec(dllexport) int Add(int x, int y);
extern "C" __declspec(dllexport) int Sub(int x, int y);
然后在 .cpp 文件中实现这两个函数:
int Add(int x, int y) { return x + y; }
int Sub(int x, int y) { return x * y; }
还需要实现 DllMain() 函数作为动态链接库的入口函数,其基本形式如下:
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; }
3、编译生成动态链接库文件:完成代码编写后,对工程进行编译,生成 .dll 文件和 .lib 文件。.dll 文件是动态链接库的可执行文件,.lib 文件是导入库文件,在进行隐式链接时需要用到。
4、静态调用法调用动态链接库:在另一个项目中,选择 File->New 命令,新建一个控制台应用程序项目,在该项目中,选择 Project->Add To Project->Components and Controls Gallery,在弹出的对话框中双击 Registered ActiveX Controls 插入控件,在控件列表中选择刚才创建的动态链接库对应的控件,将其添加到项目中,在项目的 .cpp 文件中,就可以直接调用动态链接库中的函数了。
#include "stdafx.h"
#include "051.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
`/
// The one and only application object`
CWinApp theApp;
extern "C" _declspec(dllimport) int Add(int x, int y);
extern "C" _declspec(dllimport) int Sub(int x, int y);
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
int x = 520;
int y = 521;
int add = 0;
int sub = 0;
`printf("Call WYLDll Now!
");`
add = Add(x, y);
sub = Sub(x, y);
cout << "Add: " << add << endl;
cout << "Sub: " << sub << endl;
return nRetCode;
}
5、动态调用法调用动态链接库:同样在上述的控制台应用程序项目中,在项目的 .cpp 文件中,首先使用 LoadLibrary() 函数加载动态链接库,然后使用 GetProcAddress() 函数获取要调用的函数的地址,最后通过函数指针调用函数。
HINSTANCE hDll = LoadLibrary("SimpleDll.dll");
if (hDll != NULL)
{
typedef int(*FUNC)(int, int);
FUNC pAdd = (FUNC)GetProcAddress(hDll, "Add");
FUNC pSub = (FUNC)GetProcAddress(hDll, "Sub");
if (pAdd && pSub)
{
int x = 520;
int y = 521;
int add = pAdd(x, y);
int sub = pSub(x, y);
cout << "Add: " << add << endl;
cout << "Sub: " << sub << endl;
}
FreeLibrary(hDll);
}
else
{
cout << "Failed to load functions from DLL." << endl;
}
四、实验结果分析
1、静态调用结果:通过静态调用法成功调用了动态链接库中的 Add 和 Sub 函数,并正确输出了计算结果,这表明在编译时正确地链接了动态链接库,并且在运行时能够顺利地找到并执行函数。
2、动态调用结果:使用动态调用法也能够成功地加载动态链接库并调用其中的函数,得到了正确的结果,这种方法更加灵活,可以在运行时根据需要选择加载不同的动态链接库,并且不需要在编译时就确定要链接的库。
本次实验通过建立和调用动态链接库,深入理解了动态链接库的实现原理、建立方法和调用方式,在实验过程中,掌握了使用 Microsoft Visual C++ 6.0 创建动态链接库工程、编写代码、编译生成 .dll 和 .lib 文件的方法,以及如何在其他项目中通过静态和动态两种方式调用动态链接库中的函数,通过对比静态调用和动态调用两种方式,体会到了它们各自的优缺点和适用场景,静态调用在编译时就确定了链接关系,程序运行效率较高,但不够灵活;动态调用则更加灵活,可以根据需要在运行时加载不同的库,但会带来一定的性能开销。