DLL函数封装及调用实例

动态调用的意思是显式调用,是由用户自己选择调用哪个DLL文件,在windows系统中,与动态链接库调用相关的函数主要有3个:

1.LoadLibrary,顾名思义,该函数的作用是加载DLL文件,因此该函数的参数就是你想要使用的DLL文件;

2.GetProcAddress,大概意思是获得欲使用函数的地址,其有两个参数,一个是后面会提到的句柄,另外一个就是DLL中的函数;

3.FreeLibrary,释放动态链接库。

下面通过一个实例来演示如何定义并显式调用DLL中的函数。

创建生成自己的dll文件

简单起见,我们dll中只包含一个函数,这个函数我们起名叫做multiply,作用就是实现两个数的相乘。我们新建一个项目multiplydll如下图
DLL函数封装及调用实例_第1张图片
点击确定,下一步,选择DLL,完成,如下图
DLL函数封装及调用实例_第2张图片
得到如下图所示结果,注意在源文件部分会自动生成multiplydll.cpp文件,我们将在里面添加我们的乘函数

DLL函数封装及调用实例_第3张图片
添加乘函数,编译成功如下图
DLL函数封装及调用实例_第4张图片

此时我们去项目目录下F:\src\multiplydll\Debug会看到一个生成的dll文件如下:
DLL函数封装及调用实例_第5张图片

测试调用我们生成的DLL文件中的函数

现在我们新创建一个项目,来测试调用我们生成的dll。我们新建一个项目multi_test,确定,下一步,空项目,见下面两图
DLL函数封装及调用实例_第6张图片
DLL函数封装及调用实例_第7张图片
添加源文件test做简单的测试
DLL函数封装及调用实例_第8张图片
简单起见,我们将生成的dll文件复制到当前项目下,如下图
DLL函数封装及调用实例_第9张图片
注意在新建的测试项目中需要做一点更改如下图
DLL函数封装及调用实例_第10张图片
测试代码如下:
#include
#include//这个头文件非常重要,必须加上!
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函数封装及调用实例_第11张图片

注意:上面的DLL中仅仅包含一个函数,那如果我想实现多个函数的封装调用该怎么办呢?一个可行但麻烦的方法是对每一个函数单独建一个dll,然后分别加载每个dll再调用每个函数,显然这是非常麻烦的。这个“问题”也困扰了我两天,但是突然注意到,在加载完dll之后我们获取的是dll函数中的地址啊!参数是函数名而不是dll的名字!因此,只需要一个dll就可以。其余步骤类似,下面给出一个求面积的实例,分别求矩形面积和圆形面积,代码及运行结果如下:
#include
#include
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;
}
DLL函数封装及调用实例_第12张图片

参考:http://blog.csdn.net/very_2/article/details/6534915
            http://blog.csdn.net/ojshilu/article/details/12954957

你可能感兴趣的:(C++)