动态链接库
动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。这些库函数的扩展名是 ”.dll"、".ocx"(包含ActiveX控制的库)或者 “.drv”(旧式的系统驱动程序)。
动态链接库提供了一种可以使进程调用不属于其可执行代码函数的方法,这些代码位于DLL文件中,在使用时动态被调出,且多个程序可同时调用其中的函数。
使用动态链接库可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,有一个大型网络游戏,如果把整个数百MB甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,而如果把不同功能的代码分别放在数个动态链接库中,则无需重新生成或安装整个程序就可以应用更新。
创建DLL文件
因为要考虑到执行效率,目前的系统大多是由C或C++编写成的,故DLL也是需要使用C或C++编写的。python这类作为一种解释型语言,和DLL这样编译后的二进制文件可以说不在一个维度上,目前只有使用python调用dll文件函数的方法,而暂时缺少编写的方法。
C++语言的编写当然要使用宇宙第一IDE–visual studio,具体过程如下:
首先在创建新项目中选择动态链接库
然后自定义项目名称后点击创建,即可见下图
此时生成的DllMain为函数入口,当调用dll文件时会自动执行,其具体内容如下:
BOOL APIENTRY DllMain( HMODULE hModule, //指向自身的句柄
DWORD ul_reason_for_call, //调用原因
LPVOID lpReserved //静态加载非NULL,动态加载为NULL
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: //进程创建时调用
case DLL_THREAD_ATTACH: //线程创建时调用
case DLL_THREAD_DETACH: //线程结束时调用
case DLL_PROCESS_DETACH: //进程结束时调用
break;
}
return TRUE;
}
因为内容固定,也不影响我们编写程序,所以也没有深究。个人理解是用于记录调用的信息,如调用者,调用原因,和加载方式,并表示加载进程。
#DLL编写
将一个简单弹出消息框的函数编写入DLL,正常执行会出现如下结果:
首先需要Windows.h库,然后将目标函数以C语言形式导出,默认以C++形式导出,但C++考虑重载问题,会在函数名称中加入很多符号,不便于导出。
具体代码如下:
#include<Windows.h>
extern "C" _declspec(dllexport) void def(); //以C语言形式导出
void def() {
MessageBox(NULL, L"dll loaded", L"Attention", MB_OK); //PWSTR类型转换 字符串类型前加L
}
/* 最后参数代表按钮选项
MB_OK 默认,“确定”
MB_OKCANCEL “确定”“取消”
MB_YESNO "是“”否“
MB_YESNOCANCEL "是”“否”“取消”
MB_RETRYCANCEL “重试”“取消”
MB_ABORTRETRYIGNORE "终止”“重试”“忽略” */
因为Dll文件是不可执行文件,故不可采用通常的执行不调试方法查看结果,要选择生成解决方案才能生成需要的dll文件,步骤如下:
生成的dll文件存储在项目文件夹的debug文件夹内:
动态加载
首先需要将dll复制到该项目的debug文件夹内,然后通过
typedef void(*getdef)();
定义一种新类型,设置中间变量来传导需要的函数。然后设置导入dll的句柄,并将需要的函数赋值给设置的中间变量。
HMODULE hDll = LoadLibrary(TEXT("Dll1.dll")); //句柄绑定
if (hDll == NULL)
cout << "No dll found";
getdef mes;
mes=(getdef)GetProcAddress(hDll, "def"); //函数传递
此时mes函数就相当于dll中的def函数。
静态加载
除了需要将dll文件复制到debug文件夹外,还需要将lib文件复制到项目文件内。而后通过
#pragma comment(lib, "Dll1.lib")
导入lib文件,再输入extern "C" __declspec(dllimport) void def();
来导入需要的函数。此时在本项目内可自由使用导入的函数,即可直接使用def()来执行。
总结
本次实验基本掌握了dll文件的编写及调用方法,dll文件的主要目的是便于项目维护,当线上应用需要更新时只需要更新对应文件即可。调用dll有动态静态两种方法,个人感觉动态方法更偏存储性能,只有需要的时候动态从dll文件中读取,不影响编译生成的exe文件,但写起来比较麻烦,借助自己设置的中间变量用于传递dll中的函数;而静态方法写起来很方便,只需声明需要的函数再进行调用即可,但是实质是将lib代码文件编入exe文件中,直接导致文件体积增加,只能说各有优劣。