C++ 基于vs2019创建并使用动态链接库(dll)

news2024/11/17 19:46:09

库的基本认识

静态库(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(int a, int b);
PORT int sub(int a, int b);

class PORT Circle
{
private:
	float radius;
	float area;

public:
	Circle(float);
	float getRadius();
	float getArea();
};
  • 想要研究源码的朋友看这里:
#pragma once	// 预处理指令,用于确保头文件在一个编译单元中只被包含一次,助于防止重复定义和链接错误


// 下面的宏代码是用来判断,当前那个项目在使用"头文件"
/*
	原理是:通过在DLL项目配置一个 MYDLL 的宏定义,而在 exe 项目里面不配置 MYDLL 的宏定义
	当此头文件被DLL项目使用时,MYDLL必然是有定义的,从而执行 "#define PORT __declspec(dllexport)"这一句代码
	当此头文件被exe项目使用时,MYDLL必然是没有定义,从而执行 "#define PORT __declspec(dllimport)"这一句代码
	最终在不同项目下,PORT 有着不同的功能
	在DLL项目里面,POET 将起到 "导出"的作用
	在exe项目里面,POET 将起到 "导入"的作用
*/
#ifdef MYDLL						// 如果 MYDLL 有定义,说明当前头文件是"DLL项目"在使用
#define PORT __declspec(dllexport)  // 将 PORT 定义为 导出功能
#else								// 如果 MYDLL 没有定义,说明当前头文件是"exe项目"在使用
#define PORT __declspec(dllimport)	// 将 PORT 定义为 导入功能
#endif


// 在下面编写你的代码的"声明部分"

// 导入或导出————函数
PORT int add(int a, int b);		// 详细写法:extern "C" PORT int add(int a, int b);
PORT int sub(int a, int b);		// 详细写法:extern "C" PORT int sub(int a, int b);


// 导入或导出————类
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 文件放在同一个目录下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最终文件与运行效果

  • 最终只保留以下文件即可:

在这里插入图片描述

  • 最终运行效果:
    在这里插入图片描述

结束语:希望能够帮助到你

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1710897.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三步走,Halo DB 安装指引

前文介绍了国产数据库新星 Halo 数据库是什么&#xff0c; 哈喽&#xff0c;国产数据库&#xff01;Halo DB! ★ HaloDB是基于原生PG打造的新一代高性能安全自主可控全场景通用型统一数据库。 业内首次创造性的提出插件式内核架构设计&#xff0c;通过配置的方式&#xff0c;适…

美光拟投巨资在日本广岛建DRAM厂,目标2027年底投产

美光科技&#xff08;Micron Technology&#xff09;据日本媒体报道&#xff0c;计划在日本广岛县新建一座DRAM芯片生产工厂&#xff0c;目标最快于2027年底投入运营。这一举措标志着美光在增强其内存芯片生产能力方面的又一重大步伐。 报道称&#xff0c;新工厂的总投资规模预…

【CALayer-CALayer的基本属性 Objective-C语言】

一、接下来,我们来说这个Layer啊, 1.首先,Layer能接触到的,就是我们之前说截图啊,就是我们self.view里面,有一个layer属性, [self.view.layer renderInContext:(CGContextRef t)]; 那个里面,有一个layer属性,然后呢,是CALayer类型的, 接下来,我们就来学习一…

union all 以及标量子查询执行计划

SELECT 1, (SELECT ID1 FROM TE WHERE IDA.ID2) FROM .TA A WHERE COLA X UNION ALL SELECT 1, (SELECT ID2 FROM TD WHERE IDA.ID1) FROM .TB A WHERE COLA X UNION ALL SELECT 1,COL2 AS PARENT_UUID FROM .TC a WHERE COLA X 三个union all 看着像是5个table joi…

做好开源快速开发平台研发创新 助力行业高效发展!

随着信息化时代的到来&#xff0c;科技的力量无处不在。为了提高办公效率&#xff0c;很多大中型企业倾向于使用更为先进的软件平台来助力企业降本增效。在众多助力神器之中&#xff0c;开源快速开发平台低代码技术平台深得广大新老客户朋友的喜爱&#xff0c;它与生俱来的优势…

Python中Web开发-Django框架

大家好&#xff0c;本文将带领大家进入 Django 的世界&#xff0c;探索其强大的功能和灵活的开发模式。我们将从基础概念开始&#xff0c;逐步深入&#xff0c;了解 Django 如何帮助开发人员快速构建现代化的 Web 应用&#xff0c;并探讨一些最佳实践和高级技术。无论是初学者还…

APM2.8内置罗盘校准

如果你有外置罗盘&#xff0c;可以不用校准内置罗盘&#xff0c;可以忽略此文。推荐使用外置罗盘&#xff0c;内置罗盘容易受干扰。 使用内置罗盘需要插入飞控GPS接口旁边的跳线帽。如图&#xff1a; 如果要使用内置罗盘&#xff0c;而又加了GPS的&#xff0c;记得一定要把GPS…

手机性能过剩?三年前的改名芯片卡顿明显,中端机太弱鸡了

业界人士都喜欢说手机的性能已经严重过剩&#xff0c;笔者近期从运营商购买了两款手机&#xff0c;搭载的芯片是联发科的改名芯片&#xff0c;以及高通的低端芯片&#xff0c;使用中明显卡顿&#xff0c;显示出这些改名芯片的性能早已落后于时代。 其中一款为OPPO A2&#xff0…

【Mybatis】映射文件中获取参数的符号#{}和${}的区别

在xml映射文件中获取参数的符号都是用的#{}的方式&#xff0c;其实Mybatis还支持另一种符号来接收传递过来的参数值&#xff0c;就是${}&#xff0c;他们是区别就在与底层使用jdbc的statement不一样 #{}对应的是PreparedStatementd对象来执行sql语句 ${}对应的是Statement对象…

【TCP协议中104解析】wireshark抓取流量包工具,群殴协议解析基础

Tcp ,104 ,wireshark工具进行解析 IEC104 是用于监控和诊断工业控制网络的一种标准&#xff0c;而 Wireshark则是一款常用的网络协议分析工具&#xff0c;可以用干解析TEC104 报文。本文将介绍如何使用 Wireshark解析 IEC104报文&#xff0c;以及解析过 程中的注意事项。 一、安…

Revit——(2)模型的编辑、轴网和标高

目录 一、关闭缩小的隐藏窗口 二、标高&#xff08;可创建平面&#xff0c;其他标高线复制即可&#xff09; 三、轴网 周围的四个圈和三角表示四个里面&#xff0c;可以移动&#xff0c;不要删除 一、关闭缩小的隐藏窗口 二、标高&#xff08;可创建平面&#xff0c;其他标…

JDK9-21新特性概览(持续更新)

JDK9-21新特性概览 一、JDK9新特性1.1 JEP 102: Process API Updates简介案例风险 1.2 JEP 193: Variable Handles简介案例风险 1.3 JEP 200: The Modular JDK简介案例风险 1.4 JEP 213: Milling Project Coin简介案例1.1 try-with-resources增强1.2 接口中私有方法 1.5 JEP 22…

Sentinel-2 哨兵二号数据介绍及下载

1 Sentinel-2简介 SENTINEL-2 is a European wide-swath, high-resolution, multi-spectral imaging mission. Sentinel-2 是高分辨率多光谱成像卫星&#xff0c;一颗卫星的重访周期为10天&#xff0c;两颗互补&#xff0c;重访周期为5天。分为2A和2B两颗卫星。2A于2015年6月…

【Mybatis】映射文件中获取参数的类型是集合或数组处理

基本数据类型的参数或者对象作为参数的情况&#xff0c;在Mybatis还有一些特殊处理的参数类型要特别注意&#xff1a;如果参数类型是集合Collection&#xff08;List&#xff0c;Set&#xff09;或者是数组&#xff0c;Mybatis也会把这些类型的参数封装在一个Map对象中传递到xm…

电脑记事软件哪款安全?好用且安全的桌面记事工具

在快节奏的现代生活中&#xff0c;我们每天都要用电脑处理大量的工作。电脑不仅提升了工作效率&#xff0c;还成为了我们记录重要事项和灵感的得力助手。比如&#xff0c;在策划项目时&#xff0c;我会直接在电脑上列出要点和步骤&#xff1b;在开会时&#xff0c;我也会用电脑…

Python | Leetcode Python题解之第117题填充每个节点的下一个右侧节点指针II

题目&#xff1a; 题解&#xff1a; class Solution:def connect(self, root: Node) -> Node:if not root:return Nonestart rootwhile start:self.last Noneself.nextStart Nonep startwhile p:if p.left:self.handle(p.left)if p.right:self.handle(p.right)p p.nex…

【Mybatis】映射文件中获取单个参数和多个参数的写法

xml的映射文件中获取接口方法中传来的参数是直接用#{}的方式来获取的 那么接下来&#xff0c;我们就具体来说一下获取参数里边的各种规则和用法 1.单个参数&#xff0c;比如上面的getOneUser&#xff0c;只有一个id值作为参数 Mybatis对于只有一个参数的情况下&#xff0c;不…

【深度学习】Transformer梳理

零、前言 对于transformer&#xff0c;网上的教程使用记号、术语不一 。 最关键的一点&#xff0c;网上各种图的简化程度不一 &#xff08;画个图怎么能这么偷懒&#xff09; &#xff0c;所以我打算自己手画一次图。 看到的最和善&#xff08;但是不是那么靠谱&#xff0c;我…

Qt 项目(CMake)支持多国语言(2024/05)

目录 1.在工程手动创建languages文件夹2.修改CMakeLists.txt3.在qml上随便添加一下文字内容4.执行CMake5.把.ts和.qm添加到项目中6.翻译成英文的示例7.在main里面加载语言文件8.启动软件自动获取电脑的语言遗留问题 参考:Qt 项目(CMake)设置国际化支持 1.在工程手动创建langua…

AIGC中国开发者大会:AI Agent中国落地发展现状及多模态结合具身智能的发展展望

引言 2024年5月25日&#xff0c;第三届AIGC中国开发者大会在昆仑巢成功举办。本次大会围绕“AI Agent的国内应用现状及多模态结合具身智能的发展展望”这一主题&#xff0c;邀请了多位知名企业家、投资人以及技术专家&#xff0c;共同探讨大模型在中国各行各业的应用现状及未来…