动态链接库在VS中的调用方法
应用程序要调用DLL中的函数、变量等内容,需要知道这些导出内容的地址,这个过程叫做链接。应用程序链接DLL的方式有两种:隐式(动态)链接 和 显示(动态)链接,下面逐一介绍这两种方法。
一、隐式链接
DLL项目在编译后会产生.dll文件和.lib文件,.lib文件也叫导入库文件,包含了DLL各种导出资源的链接信息,通过导入库文件来获取DLL的链接信息,就是DLL中各种导出资源实际代码的指针,通过这些指针,就可以具体执行DLL中的代码了,所以本质还是通过指针来实现的。
隐式链接使用DLL的基本流程
(1)在应用程序项目中引用导入库文件(.lib),有下面三种方法
1)在项目属性中设置; 2)使用指令 #pragma comment
; 3)直接添加到解决方案视图中去。
(2)在应用程序中包含头文件
(3)在应用程序中调用DLL中的数据、函数或者类
1)在项目属性中设置
第一步:首先准备好我们在VS中DLL项目,其中头文件和源文件如下
第二步:在解决方案中添加一个MFC项目来调用Test.dll中的f()函数,项目名称为UseDll,在“MFC应用程序向导”的对话框中选择应用程序类型为“基于对话框”。(有些同学可能添加不了MFC项目,是因为在VS中对应的模块没有安装,需要在导航器里面添加下载一下)
在侧面的工具箱中拖入一个按钮在对话框中,双击按钮,跳转到下面的cpp文件中,把f()函数加入进去,再包含一下对应的Test.h头文件。
再配置一下对应的项目属性,分别添加 库目录的路径 和 所需要添加的库名.lib
保存好后,右击调试新示例运行该项目就可以了。
2)使用指令 #pragma comment
第一步:首先准备好我们在VS中DLL项目(同上)
第二步:同样在解决方案中添加一个对话框项目UseDll2来调用Test.dll中的f()函数,其它操作和第一种方法完全一样,就是有一步不同:第一种方法中配置项目属性的附加依赖项-输入-Test.lib 这一操作被#pragma comment(lib,"Test.lib")
代替了,也就是说这一步直接写进代码里面了,不需要再手动配置了。
3)直接添加到解决方案视图中去(最直接最简单)
直接再文件夹中找到要导入的Test.lib文件,将其拖拽到MFC项目名称上,然后松手,再资源文件下就会多了这个文件
接下来只需要在UseDllDlg.Cpp中包含一下头文件Test.h即可,就可以调用成功了。
二、显式链接
显示链接不需要使用导入库文件(.lib文件),二十通过三个API函数实现动态库的调用。先通过LoadLibrary()函数来加载动态链接库,再通过GetProcAddress()来获取动态链接库导出函数的地址并执行导数函数,最后通过FreeLibrary()来卸载动态链接库。下面简要介绍一下这三个函数:
LoadLibrary()函数原型
HMODULE WINAPI LoadLibrary(LPCTSTR lpFileName);
其中参数lpFileName
指向要加载的动态链接库的路径或者文件名,如果lpFileName
不是路径而是一个文件名,则这个函数会通过标准的搜索策略来搜索这个文件。如果函数成功找到文件,则返回加载成功的动态链接库模块句柄,如果失败返回NULL,失败错误代码可以通过函数GetLastError()来获得。
GetProcAddress()函数原型
FARPROC GetProcAddress(HMODULE, hModule, LPCSTR lpProName);
其中参数hModule
是动态链接库的模块句柄,lpProName
是动态链接库中导出函数或者变量的名称,如果这个函数成功,则返回期望导出的函数或者变量的地址,否则返回NULL,失败错误代码可以通过函数GetLastError()来获得。
FreeLibrary()函数原型
BOOL FreeLibrary(HMODULE, hModule);
其中参数hModule
是动态链接库的模块句柄,如果函数成功则返回非零,否则返回零。
下面通过例子来说明显示调用
同样准备好下面的项目
其中,Test项目是和上面类似
UseDll.Cpp中的显示链接代码如下:
// UseDll.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
//定义函数指针类型
typedef int(*FUNC)(TCHAR *, int);
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hDll = NULL;
FUNC myf;//定义函数
int res;
hDll = LoadLibrary(_T("Test.dll"));
if (!hDll)
{
puts("Test.dll加载失败");
goto end;
}
myf = (FUNC)GetProcAddress(hDll, "f1");
if (!myf)
{
puts("获取函数失败");
goto end;
}
res = myf(_T("你好"), 10);
printf("返回值是:%d\n", res);
FreeLibrary(hDll);
end:
return 0;
}
右击调试新示例运行UseDll项目就可以了。