大家好,我是孤帆冒雨行,上一期我们说到如何用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:甥敳獲FanDesktopDLLTestDLLTest",最后单击确定按钮,这一步完成。
3.2 属性页->配置属性->链接器->常规->附加依赖项,点击附加依赖项右侧的...,在弹出的窗口中输入MyDLL.lib,如图所示,最后单击确定,再点击属性页的确定,配置就完成了。
再简单解释一下:附加库目录是指向你的lib目录,附加依赖项是添加库目录中.lib文件的名称。
4.将MyDLL.h文件复制到你的项目文件夹下,在VS2008中的解决方案资源管理器中选择头文件,单击右键,添加->现有项,选择MyDLL.h。
5.在源文件中添加一个名为main.cpp新建项,并复制以下代码到文件中。
#include #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.在菜单中选择调试->开始执行(不调试) 来运行我们的项目,如图所示。
方法2.显式调用(动态调用)
1.首先我们需要只需准备一个文件,即MyDLL.dll,在后面可以复制到项目文件夹下。
2.新建一个类型为控制台应用程序的空项目,命名为DLLTest。
3.在源文件中添加一个名为main.cpp新建项,并复制以下代码到文件中。
#include #include 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