「C++学习笔记」动态链接库(Dll):C++动/静态调用C++的dll

接上一篇:「C++学习笔记」动态链接库(Dll):创建与调试

因为本文中对用到的C++ dll的详细情况没有细说,全部在上一篇文章中。

所以建议先去速览一下,以便看本文的时候不至于懵逼。

写好的dll如何调用呢,使用C++调用动态链接库时有两种方式:静态和动态

1、C++静态方式调用dll

这种方式基本和上一篇中dll的调试性质一样,好处是你可以使用dll中的原函数名,在代码上比动态调用要好看的多。

1.1、先建个项目再说

在dll的解决方案目录下创建一个控制台项目:“CppUseDllStatic”

创建在同一个目录下是为了代码管理方便,你也可以在其他地方创建。

1.2 静态调用的配置

静态调用的方式需要三个主要文件,

1:dll项目中声明所有暴露函数的头文件(例如我之前建好的项目中的“CppDllDemo.h”),

2:“xxx.dll”文件,即动态链接库(如我的是“CppDllDemo.dll”),

3:“xxx.lib”文件,与“.dll”同时生成的,且在同一目录下(如 我的是“CppDllDemo.lib”)

 打开项目属性,把头文件所在路径复制到【VC++目录】→【包含目录】中。

(这样做是为了在#include时直接写头文件名,如果你不嫌麻烦,直接include该头文件的全路径名也行,又或者把这个头文件复制到该项目的根目录下再include也行,随你)

在上图的库目录中,加入“xxx.lib”文件所在的目录,然后在【链接器】→【输入】→【附加依赖项】中加入lib文件名:“xxx.lib”

如果你觉得加入库目录、添加附加依赖项很麻烦,你也可以在代码中,用如下代码代替:

#pragma comment(lib, "D:\\code\\CppDllDemo\\x64\\Debug\\CppDllDemo.lib")

接着就是把“xxx.dll”文件放到控制台程序生成的“xx.exe”文件所在目录。 

1.3 完成以上,就可以在代码中进行调用了

调用的示例代码如下:

#include <iostream>
#include <CppDllDemo.h> //如果没有“包含目录”,就写全路径吧:D:\\balabalabala\\CppDllDemo.h

//如果没有加“库目录”和“附加依赖项”,就使用下面这句吧
//#pragma comment(lib, "D:\\code\\CppDllDemo\\x64\\Debug\\CppDllDemo.lib")

using namespace std;

int main()
{
	double result = Add(4.5, 11.2);
	cout << "result = " << result << endl;
	SayHello();
	cin.get();
}

 有用过opencv的同学一定觉得很眼熟:「图像处理」OpenCV的安装与配置

opencv的配置,就是静态方式加载dll的方式。

2、动态方式调用dll

协同开发的很多时候,都只有dll文件而没有“.h”和“.lib”文件,而且很多时候,dll的开发人员并不愿意提供这两个文件,再者,用久了就会发现,很多小的dll,动态调用方式是要比静态方便的多的。

如何以动态的方式调用呢,只要有“xxx.dll”文件………………和“接口说明文档”(谁开发的找谁要)

之所以要文档,是你必须知道dll中的函数有哪些,每个函数的名称和参数类型是什么。

接下来直接上代码:

#include <iostream>
#include <Windows.h> //新版本里面,要包含下面的头文件就必须要Windows.h
#include <libloaderapi.h> //需要用到下文中的LoadLibrary()

using namespace std;

//导入动态库  
//使用了unicode字符集,LoadLibrary 是LoadLibraryW(LPCWSTR lpLibFileName),需要注意参数类型转换
HMODULE DllHolder = LoadLibrary(L"D:\\code\\CppDllDemo\\x64\\Debug\\CppDllDemo.dll");

//定义与dll中Add函数相同的函数指针类型,dll中Add函数的参数类型是(double, double)
typedef double(_stdcall* pAdd)(double, double);
//在dll中按“Add”名称找到函数并赋值给pAdd的实例函数指针(你可以随意起名)
pAdd AddFunc = (pAdd)GetProcAddress(DllHolder, "Add");

//下面两行参考上面的注释吧
typedef void(_stdcall* pSayHello)();  //dll中SayHello函数没有入参
pSayHello SayHelloFunc = (pSayHello)GetProcAddress(DllHolder, "SayHello");

int main()
{
	double result = AddFunc(4.5, 11.2);
                    //也可以这样使用:(*AddFunc)(4.5, 11.2)
	cout << "result = " << result << endl;
	SayHelloFunc();
	cin.get();
}

以上就是C++调用C++ dll的动态与静态方式,贴一张运行成功的截图以做纪念:

3、最重要的一点

我们调用dll进行编译和最终交付使用(运行编译生成的exe)是两回事,是两个环境。

所以,在静态调用时,不管你在编译时怎么配置,最终的exe运行的时候所调用的dll都是从其自身所在目录下开始找“xxx.dll”文件,所以你写好程序后,要记得吧用到的dll都复制到你生成的exe文件同目录中去。

对于动态调用,代码中会显式指定“xxx.dll”的路径,指要路径正确,就可以了。

发布了21 篇原创文章 · 获赞 5 · 访问量 3671

猜你喜欢

转载自blog.csdn.net/Raink_LH/article/details/102571075