动态调用的意思是显式调用,是由用户自己选择调用哪个DLL文件,在windows系统中,与动态链接库调用相关的函数主要有3个:
1.LoadLibrary,顾名思义,该函数的作用是加载DLL文件,因此该函数的参数就是你想要使用的DLL文件;
2.GetProcAddress,大概意思是获得欲使用函数的地址,其有两个参数,一个是后面会提到的句柄,另外一个就是DLL中的函数;
3.FreeLibrary,释放动态链接库。
下面通过一个实例来演示如何定义并显式调用DLL中的函数。
创建生成自己的dll文件
简单起见,我们dll中只包含一个函数,这个函数我们起名叫做multiply,作用就是实现两个数的相乘。我们新建一个项目multiplydll如下图
点击确定,下一步,选择DLL,完成,如下图
得到如下图所示结果,注意在源文件部分会自动生成multiplydll.cpp文件,我们将在里面添加我们的乘函数
添加乘函数,编译成功如下图
此时我们去项目目录下F:\src\multiplydll\Debug会看到一个生成的dll文件如下:
测试调用我们生成的DLL文件中的函数
现在我们新创建一个项目,来测试调用我们生成的dll。我们新建一个项目multi_test,确定,下一步,空项目,见下面两图
添加源文件test做简单的测试
简单起见,我们将生成的dll文件复制到当前项目下,如下图
注意在新建的测试项目中需要做一点更改如下图
测试代码如下:
#include<iostream>
#include<Windows.h>//这个头文件非常重要,必须加上!
using namespace std;
typedef int(*dllfunc)(int a, int b);//这里的dllfun形式上和我们生成的DLL文件中的函数一致,我们的dll中定义的函数有两个整型参数,因此这里也是int a,int b
int main()
{
HINSTANCE hdll;//定义一个句柄实例,来获取dll的实例地址
//这里为简单起见,我们直接将生成的multiply.dll文件复制到当前项目下,否则下面一句你需要替换成dll的地址
hdll = LoadLibrary("multiplydll.dll");//加载生成的dll文件,因为我们把生成的dll文件复制到当前项目目录下了,所以直接写就行了
//下面判断当前dll是否加载成功
if (hdll == NULL)
{
cout << "DLL加载失败" << endl;
return 0;
}
//如果通过上面则表明加载成功了,下面我们需要取出dll里面函数的地址
dllfunc add_obj = (dllfunc)GetProcAddress(hdll, "multiply");//此处两个参数一个是我们的句柄,另外一个是dll中函数名,取出来给add_obj
//同样,取址是否成功呢?判断一下!
if (add_obj == NULL)
{
cout << "获取DLL中函数地址失败!" << endl;
return 0;
}
//获取函数地址成功后,我们就可以使用dll中的函数了
cout << add_obj(3, 5) << endl;
FreeLibrary(hdll);
return 0;
}
结果
注意:上面的DLL中仅仅包含一个函数,那如果我想实现多个函数的封装调用该怎么办呢?一个可行但麻烦的方法是对每一个函数单独建一个dll,然后分别加载每个dll再调用每个函数,显然这是非常麻烦的。这个“问题”也困扰了我两天,但是突然注意到,在加载完dll之后我们获取的是dll函数中的地址啊!参数是函数名而不是dll的名字!因此,只需要一个dll就可以。其余步骤类似,下面给出一个求面积的实例,分别求矩形面积和圆形面积,代码及运行结果如下:
#include<iostream>
#include<Windows.h>
using namespace std;
typedef double(*dllfun1)(double l, double d);
typedef double(*dllfun2)(double r);
int main()
{
double width, length;
cout << "please enter the width and length of a rectangle:" << endl;
cin >> width >> length;
HINSTANCE hdll;
hdll = LoadLibrary("myArea.dll");
if (hdll == NULL)
{
cout << "DLL加载失败" << endl;
return 0;
}
dllfun1 re = (dllfun1)GetProcAddress(hdll, "rect");
if (re == NULL)
{
cout << "获取DLL函数地址失败" << endl;
return 0;
}
cout << "Area of the rectangle is:" << re(length, width) << endl;
double radius;
cout << "please enter the radius of a circle:" << endl;
cin >> radius;
dllfun2 ci = (dllfun2)GetProcAddress(hdll, "circle");
if (ci == NULL)
{
cout << "获取DLL函数地址失败" << endl;
return 0;
}
cout << "Area of the circle is:" << ci(radius) << endl;
FreeLibrary(hdll);
return 0;
}
参考:http://blog.csdn.net/very_2/article/details/6534915
http://blog.csdn.net/ojshilu/article/details/12954957