C++ 基于vs2019创建并使用动态链接库(dll)
C++ 基于vs2019创建并使用动态链接库(dll)
本文将详细介绍如何在C++中使用Visual Studio 2019创建和使用动态链接库(DLL)。通过本文,你将了解静态库和动态库的基本概念,掌握DLL的创建过程和使用方法,并通过具体的代码示例加深理解。
库的基本认识
静态库(Static Library)
基本概念:静态库是在编译时链接到目标程序中的库文件。它包含了程序运行所需的所有函数和数据,这些函数和数据会被直接嵌入到最终生成的可执行文件中。静态库通常以
.a
(在Unix-like系统中)或.lib
(在Windows系统中)为文件扩展名。作用:
代码重用:静态库允许开发者将常用的代码或功能封装成库,以便在多个项目或模块中重复使用。
隐藏实现细节:通过静态库,开发者可以隐藏某些函数或数据的实现细节,只提供必要的接口供其他开发者使用。
减小可执行文件大小:虽然静态库本身较大,但多个使用相同静态库的可执行文件在磁盘上的总存储空间可能会减小,因为它们共享相同的代码段。
增加编译时间:由于静态库在编译时链接到目标程序中,因此每次编译都会重新处理库中的代码,这可能导致编译时间增加。
不便于更新:如果静态库中的代码需要更新,那么所有使用该库的可执行文件都需要重新编译。
动态库(Dynamic Library)
基本概念:动态库是在运行时链接到目标程序中的库文件。它包含了程序运行所需的一些函数和数据,但这些函数和数据在程序运行时才会被加载到内存中。动态库通常以
.so
(在Unix-like系统中)或.dll
(在Windows系统中)为文件扩展名。作用:
代码重用:与静态库类似,动态库也允许开发者将常用的代码或功能封装成库,以便在多个项目或模块中重复使用。
节省磁盘空间:由于动态库在多个可执行文件之间共享,因此可以节省磁盘空间。
减少内存使用:当多个程序使用相同的动态库时,它们可以共享内存中的同一份库代码,从而减少内存使用。
便于更新:如果动态库中的代码需要更新,只需要替换库文件即可,而无需重新编译使用该库的可执行文件。
增加加载时间:由于动态库在程序运行时才链接,因此可能导致程序加载时间增加。此外,如果动态库丢失或损坏,程序将无法正常运行。
总的来说,静态库和动态库各有优缺点,开发者需要根据具体需求选择合适的库类型。例如,在需要隐藏实现细节或减小可执行文件大小的场景中,可以使用静态库;而在需要节省磁盘空间、减少内存使用或便于更新的场景中,可以使用动态库。
文件结构与原理
在DLL项目中,建议将函数、类等代码的声明放到.h
的头文件中,而它的具体实现将放到.cpp
文件中。这样做不仅可以让项目的结构更加清晰,而且还起到一个很重要的作用:在.h
头文件中的代码,可以巧妙利用宏定义,实现动态的声明——头文件为DLL项目的.cpp
文件的函数、类等声明"向外导出",又可以为未来要使用DLL的应用程序声明"向里面导入"。
DLL的创建
创建一个空项目
编写你的代码
在MyDll.h
文件中编写代码:
#pragma once
#ifdef MYDLL
#define PORT __declspec(dllexport)
#else
#define PORT __declspec(dllimport)
#endif
PORT int add;
PORT int sub;
class PORT Circle
{
private:
float radius;
float area;
public:
Circle(float);
float getRadius();
float getArea();
};
在MyDll.cpp
文件中编写:
#include "MyDll.h"
/*
这里是DLL项目的具体实现:
而在DLL项目的属性中,我们需要确保MYDLL宏被定义
这通常是通过在项目配置的属性页中的“C/C++” -> “预处理器” -> “预处理器定义”中添加MYDDL来完成的
*/
// 实现在"头文件"里面声明的函数和类...
// 如下所示:
int add(int a, int b) // 加法
{
return a + b;
}
int sub(int a, int b) // 减法
{
return a - b;
}
Circle::Circle(float radius) // 实现一个圆
{
this->radius = radius;
this->area = 3.14 * radius * radius;
}
float Circle::getRadius()
{
return this->radius;
}
float Circle::getArea()
{
return this->area;
}
Release模式
修改项目属性
- 配置类型:
生成DLL文件
找到DLL文件
在"解决方案" MySolution1 中,找到并打开Release文件夹。如果能够找到下面两个文件就说明,生成DLL文件成功!建议复制这两个文件,并保存到一个新的文件夹中。
找到DLL项目的头文件
回到刚才的"解决方案" MySolution1 中,点击MyDll文件夹。建议将这个头文件复制一份,保存到刚刚存放了DLL文件的文件夹里面。
DLL的三个文件
我们通过创建DLL项目,做了一系列的步骤,最终就是为了得到上面的三个文件!到此为止,我们就完成了DLL文件的创建任务。在上面的操作里,我们在DLL文件里面,声明了一些函数和类,而且实现了这些函数和类。对于这些封装好的功能,我们如何才能使用它呢?接下来,让我们一起来看看如何使用我们所编写的DLL文件。
DLL的使用
创建一个空白的项目
我们将创建一个项目,作为一个应用程序(exe),然后在这个应用程序里面,使用我们的DLL文件。
Release模式
将模式修改为:Release(实现与DLL项目统一模式)。
引入必要文件
原理:
要使用DLL里面封装好的实现代码,我们先要引入DLL头文件里面的声明代码。也就是说,我们想要导入头文件#include<MyDll.h>
。但是,在当前这个"应用程序"的项目中,vs2019是不知道我们已经写好了这个头文件的。所以,我们需要做一些配置,告诉vs2019我们的头文件放在了哪里。
步骤:
- 告诉vs2019去哪个目录找头文件
- 告诉vs2019去哪个目录找lib文件
- 告诉vs2019在使用链接器进行链接时,链接哪一个lib文件
编写应用程序代码
源码:
#include<iostream>
#include<MyDll.h>
using namespace std;
int main()
{
int first, secend, radius;
cout << "请输入两个整数:";
cin >> first >> secend;
cout << "两数之和:" << add(first, secend) << endl;
cout << "两数之差:" << sub(first, secend) << endl;
cout << "请输入圆的半径:" << endl;
cin >> radius;
Circle myCircle(radius);
cout << "半径:" << myCircle.getRadius() << endl;
cout << "面积:" << myCircle.getArea() << endl;
system("pause");
return 0;
}
生成应用程序(exe)
生成exe文件。找到生成的exe文件,并将它和dll文件放在同一个目录下。
最终文件与运行效果
最终只保留以下文件即可:
最终运行效果:
结束语
希望本文能够帮助读者更好地理解和掌握C++中动态链接库的使用方法。本文来自掘金,原文链接:C++ 基于vs2019创建并使用动态链接库(dll)。