VS2008 C++ 调用一个简单的DLL文件

上一期我们说到如何用VS2008 C++生成一个简单的DLL文件,这次我们来试着去调用它。

C++调用DLL文件的方法也是有两种,分为显示调用与隐式调用,也称为动态调用与静态调用。

静态调用是通过链接器将DLL函数的导出写进可执行文件中,而动态调用不是链接时完成的,是在运行时完成的,动态调用不会在可执行文件中写入DLL相关的信息。

大家可以根据实际项目的需求来选择哪种调用方法。

接下来介绍如何调用DLL的内容,部分需要参考上一篇文章的内容。

链接:https://www.cnblogs.com/cokefan/p/13302971.html

方法1.隐式调用(静态调用)

1.首先需要准备三个文件,生成DLL时的.h头文件、.lib静态库文件和.dll动态库文件。这里我们使用上期生成的MyDLL.h、MyDLL.lib和MyDLL.dll,在后面可以复制到项目文件夹下。

2.新建一个类型为控制台应用程序的空项目,命名为DLLTest,具体创建项目的方法可以参考我的上一篇文章。这里就不再详细介绍了。

3.创建好项目之后,在菜单栏选择项目->属性(ALT+F7)。这里进行两项属性配置:

​ 3.1 属性页->配置属性->链接器->常规->附加库目录,点击附加库目录右侧的...,如图在弹出的窗口选择插入新行按钮,单击...,选择你放MyDLL.lib文件的目录。这里我就放在了项目文件夹下面,所以目录就是"C:\Users\Fan\Desktop\DLLTest\DLLTest",最后单击确定按钮,这一步完成。

​ 3.2 属性页->配置属性->链接器->常规->附加依赖项,点击附加依赖项右侧的...,在弹出的窗口中输入MyDLL.lib,如图所示,最后单击确定,再点击属性页的确定,配置就完成了。

再简单解释一下:附加库目录是指向你的lib目录,附加依赖项是添加库目录中.lib文件的名称。

4.将MyDLL.h文件复制到你的项目文件夹下,在VS2008中的解决方案资源管理器中选择头文件,单击右键,添加->现有项,选择MyDLL.h。

5.在源文件中添加一个名为main.cpp新建项,并复制以下代码到文件中。

#include <iostream>
#include "MyDLL.h"

int main()
{
	std::cout << "add(3,4):" << add(3,4) << std::endl;
	std::cout << "sub(9,2):" << sub(9,2) << std::endl;
	return 0;
}

6.在菜单中选择调试->开始执行(不调试) 来运行我们的项目,如图所示。

2020-09-02更新:新学到了另一种链接静态库的方法,将上述第三步省略,在第五步中的代码中第三行加入#pragma comment(lib, "MyDLL.lib")可以实现同第三步相同的操作。

方法2.显式调用(动态调用)

1.首先我们需要只需准备一个文件,即MyDLL.dll,在后面可以复制到项目文件夹下。

2.新建一个类型为控制台应用程序的空项目,命名为DLLTest。

3.在源文件中添加一个名为main.cpp新建项,并复制以下代码到文件中。

#include <iostream>
#include <windows.h>

typedef int(*func)(int, int);

int main()
{
	LPCWSTR dllName = L"MyDLL.dll";
	const char* funName = "add";

	HMODULE hDLL = LoadLibrary(dllName);//通过dll名称加载dll,将dll放在该工程根路径即可
	if(hDLL != NULL)
	{
		func func_add = func(GetProcAddress(hDLL, funName));//获取导入到应用程序中的函数指针,根据函数名取得 
		//func func_add = func(GetProcAddress(hDLL, MAKEINTRESOURCE(1)));//根据直接使用DLL中函数出现的顺序号,可以通过Depends软件了解,也是在.def文件中定义的顺序
		if(func_add != NULL)
			std::cout << "func_add(3,4):" << func_add(3, 4) << std::endl;
		else
		{
			std::cout << "Cannot Find Function : " << funName << std::endl;
		}
		FreeLibrary(hDLL);//使用完需要释放
	}
	else
	{
		std::wcout << "Cannot Find dll : " << dllName << std::endl;
	}

	return 0;
}

4.执行项目,在菜单栏中选择调试->开始执行(不调试)。运行结果如图。

简单的解释:

typedef int(*func)(int, int);

这里我们定义一个指向与DLL中所需函数类型相同的原型指针。

例如DLL中的 int add(int, int); 在声明中参数名可省略,但是参数类型不可省略。

关于dllName的类型LPCWSTR,它的定义是typedef const wchar_t* LPCWSTR;

LPCWSTR是一个指向unicode编码字符串的32位指针,所指向字符串是wchar型,而不是char型。

所以在第8行定义字符串的前面要加L,第26行输出时需要使用std::wcout,这也是输出宽字符专用的。

如果希望以上代码可以使用const char*型来输出,可以更改配置,具体操作如下:

菜单栏->项目->属性->配置属性->常规->字符集,本身是使用Unicode字符集,更改为使用多字节字符集,即可。

上述代码的第8行和第26行分别改为,

	const char* dllName = "MyDLL.dll";
	std::cout << "Cannot Find dll : " << dllName << std::endl;

程序也可以正常运行了,在实际使用中可以根据实际项目需求进行选择。


参考资料:

[1]VS2008 C++生成一个简单的DLL文件

https://www.cnblogs.com/cokefan/p/13302971.html

posted @ 2020-07-21 09:40  CokeFan  阅读(614)  评论(0编辑  收藏  举报