VS中动态库的创建和调用

VS中动态库的创建和调用

是写好的现有的,成熟的,可以复用的代码。库的存在形式本质上来说库是一种可执行代码的二进制。

​ 库有两种:静态库(.a、.lib)和动态库(.so、.dll)。所谓静态、动态是指链接阶段,静态库的链接阶段是在项目编译的时候静态链接。动态库是在程序运行的时候由代码加载链接。

​ 静态库和动态库的区别主要是在链接阶段处理库的方式不同而区分的。

静态库

概念

​ 静态库指的是在链接阶段直接将库和目标文件一起打包成可执行文件的方式所使用的库就称为静态库。

体现形式

​ .a 或者 .lib 文件

优缺点

优点 :①使可执行文件依赖项少,已经被打包到可执行文件中了。 ②编译阶段完成链接,执行期间代码装载速度快

缺点:①使可执行文件变大。②若作为其他库的依赖库,将会造成多余的副本,因为必须与目标文件打包。③升级不方便,升级必须重新编译

静态库的创建
  1. 使用VS创建一个空项目;
  2. 创建空项目之后将项目设置为静态库(点击项目 -> 属性 -> 常规 -> 配置类型)中修改;
  3. 配置项目lib输出位置(常规 -> 输出目录 :指的是dll输出的文件位置);
  4. 书写接口,在静态库中,只要是可以允许访问的函数和类都可以被使用,没有特别的函数导入和导出。

例程:

#pragma once
#include <iostream>class Arithmetic
{
public:// Returns a + bstatic double Add(double a, double b);//可以调用// Returns a - bstatic double Subtract(double a, double b);//可以调用// Returns a * bstatic double Multiply(double a, double b);//可以调用// Returns a / bstatic double Divide(double a, double b);//可以调用void fun2();//可以调用private:static void fun();//不可以调用void fun1();//不可以调用
};
#include "Arithmetic.h"double Arithmetic::Add(double a, double b)
{return a + b;
}double Arithmetic::Subtract(double a, double b)
{return a - b;
}double Arithmetic::Multiply(double a, double b)
{return a * b;
}double Arithmetic::Divide(double a, double b)
{return a / b;
}void Arithmetic::fun2() {std::cout << "公共  void Arithmetic::fun2()" << std::endl;
}void Arithmetic::fun() {std::cout << "私有  static void Arithmetic::fun()" << std::endl;
}
void Arithmetic::fun1() {std::cout << "私有  void Arithmetic::fun1()" << std::endl;
}
静态库的调用
  1. 创建一个项目
  2. 配置项目属性,导入静态库位置。
  3. 导入头文件:C/C++ -> 常规 -> 附加包含目录 :指的是需要使用的自己编写的头文件
  4. 导入库文件:链接器 -> 常规-> 附加库目录 :指的是在调用的时候声名需要使用的lib文件。
  5. 添加导入lib名称:链接器 -> 输入 -> 附加依赖项 :指的是在调用的时候声名需要使用的lib文件。
  6. 引入库的头文件,之后直接使用库即可。

动态库

概念

动态库指的是在程序运行过程中动态加载库的方式使用的库,也就是动态库的链接是发生在程序运行时期的,它和可执行文件是分开的,只是可执行文件在运行的某个时期调用了它。

体现形式

​ .DLL、.lib 和 .a 、.so ;

优缺点

好处:程序自身的体积不会因为动态函数库变大。
缺点:就是程序运行过程中使用到了这些函数库内的功能时,万一系统特定的位置没有对应的动态库。就会造成程序崩溃或者各种奇怪的问题。

动态库的创建

在介绍动态库的创建之前,我们先来了解以下的宏。

#pragma once
#ifdef PUBFUN_EXPORTS
#define PUBUTIL_DLL __declspec(dllexport)
#else
#define PUBUTIL_DLL __declspec(dllimport)
#endif

MSVC编译器提供了一系列C/C++的扩展来指定符号的导入导出,即__declspec属性关键字。

dllexport与dllimport存储级属性是微软对C和C++的扩展,可用于从dll中导入或导出函数、数据、对象(objects)

__declspec(dllexport) 表示该符号是从本DLL导出的符号。

__declspec(dllimport) 表示该符号是从别的DLL中导入的。

我们在创建动态库的时候需要用到上面的宏。

创建方式1:使用空项目

  1. 使用VS创建一个空项目;
  2. 创建空项目之后将项目设置为动态库(点击项目 -> 属性 -> 常规 -> 配置类型)中修改;
  3. 配置项目lib 和 DLL 输出位置(常规 -> 输出目录 :指的是dll输出的文件位置);
  4. 创建一个header.h (此文件名可以自由定义)定义之后将上面的宏写入到文件中(宏名称可以自己定义)。
  5. 使用定义的宏定义动态库导出的函数或者类。
  6. 编译生成动态库。

例程:

创建动态库导出导入宏

//header.h
#pragma once
#ifdef BD_TEST
#define BDTEXT_DLL __declspec(dllimport)
#else
#define BDTEST_DLL __declspec(dllexport)
#endif

使用宏定义导出的函数

//testDLL.h
#pragma once
#include "header.h"int  BDTEXT_DLL add(int a, int b);

导出函数功能的实现

//testDLL.cpp
#include "testDLL.h"int add(int a, int b) {return a + b;
}

编译:

在这里插入图片描述
这就是最后编译出来的lib和dll库。

创建方式2:直接创建动态库项目

使用直接创建动态库项目,会在项目中生成一个dllMain.cpp的文件。如下:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;
}

根据微软官网说明:

DllMain是动态链接库 (DLL) 的可选入口点。 当系统启动或终止进程或线程时,它将使用进程的第一个线程为每个加载的 DLL 调用入口点函数。 使用 LoadLibraryFreeLibrary 函数加载或卸载 DLL 时,系统还会调用 DLL 的入口点函数。

之后其他的接口函数和接口类和空项目的建立是一样的。

动态库的调用
  1. 创建一个项目
  2. 导入头文件:C/C++ -> 常规 -> 附加包含目录 :指的是需要使用的自己编写的头文件
  3. 导入库文件:链接器 -> 常规-> 附加库目录 :指的是在调用的时候声名需要使用的lib文件。
  4. 添加导入lib名称:链接器 -> 输入 -> 附加依赖项 :指的是在调用的时候声名需要使用的lib文件。
  5. 引入库的头文件,之后直接使用库即可。
  6. 将于lib配套的dll放到执行文件exe所在的文件目录下。

例程:

配置头文件

在这里插入图片描述

配置lib文件位置

在这里插入图片描述

配置需要使用lib文件

在这里插入图片描述

配置完成之后编写代码

#include <iostream>
#include <testDLL.h>//引入头文件int main() {std::cout << add(2, 5) << std::endl; //调用库中的函数getchar();return 0;
}

注意点:

1、没有设置为导出的函数名称或者类,无法在外部调用dll使用。导出的函数和类必须使用导出宏修饰。

项目常见配置项

常规 -> 输出目录 :指的是dll输出的文件位置

常规 -> 中间目录 :指的是中间件的输出位置

常规 -> 配置类型 :指的是项目类型

VC++目录 -> 包含文件 :指的是三方库文件的头文件位置

VC++目录 -> 库目录 : 指的是三方库文件(.dll .lib)文件

C/C++ -> 常规 -> 附加包含目录 :指的是需要使用的自己编写的头文件

C/C++ -> 预处理器 -> 预处理器定义 : 指的是我们需要配置的宏定义

链接器 -> 输入 -> 附加依赖项 :指的是在调用的时候声名需要使用的lib文件。

链接器 -> 高级 -> 导入库 : 指的是lib导出的文件位置

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Find My游戏手柄|苹果Find My技术与手柄结合,智能防丢,全球定位

游戏手柄是一种常见电子游戏机的部件&#xff0c;通过操纵其按钮等&#xff0c;实现对游戏虚拟角色的控制。随着游戏设备硬件的升级换代&#xff0c;现代游戏手柄又增加了&#xff1a;类比摇杆&#xff08;方向及视角&#xff09;&#xff0c;扳机键以及HOME菜单键等。现在的游…

uniapp 文字超出多少字,显示收起全文按钮效果demo(整理)

收起展开 <template><view class"font30 color000 mL30 mR30"><text :class"showFullText ? : clamp-text">{{ text }}</text><view v-if"showToggleBtn && text.length > 42" click"toggleShowFu…

Elasticsearch安装Windows版

目录 1.&#xff1a;下载安装包&#xff0c;选择指定的版本&#xff0c;这里选择了7.8.0&#xff0c;官网下载地址&#xff1a; ​编辑 2&#xff1a;下载好之后解压&#xff0c;解压之后是这样的&#xff1a; 3&#xff1a;配置环境变量&#xff0c;跟JDK一样&#xff0c;…

如何高效编写测试用例

本话题暂不探讨是否有必要编写详细的测试用例&#xff0c;在确定要交付详细的测试用例这个前提下&#xff0c;分享如何更高效地完成测试用例的编写。 对齐测试用例需求 首先、明确要完成的测试用例文档目标要求&#xff0c;模板、范围、粒度等。 用例文档使用者&#xff1a;…

JDBC初体验(二)——增、删、改、查

本课目标 理解SQL注入的概念 掌握 PreparedStatement 接口的使用 熟练使用JDBC完成数据库的增、删、改、查操作 SQL注入 注入原理&#xff1a;利用现有应用程序&#xff0c;将&#xff08;恶意的&#xff09;SQL命令注入到后台数据库引擎执行能力&#xff0c;它可以通过在…

element input组件自动失去焦点问题解决

最近在 Vue3 ElementPlus 中&#xff0c;使用 el-input 组件时&#xff0c;如果设置了 v-model&#xff0c;那么在每次改变内容后后&#xff0c;input 会自动失去焦点&#xff0c;这样会导致用户无法输入多个字符。 一、问题原因 如上图所示&#xff0c;配置项的 Name 和 Cod…

VSCode使用技巧

选择python 解释器 使用快捷键CtrlShiftP Python: Select Interpreter快捷键 返回上一次光标的位置 重新设置一下 navigate

jmeter分布式服务搭建

目录 一、环境准备 二、 安装包下载 三 、安装jdk 四 、控制机安装 4.1 解压压缩包 4.2 修改 bin/jmeter.properties 4.3 修改 bin/system.properties 五、执行机安装 5.1 解压安装包 5.2 修改 bin/jmeter.properties 5.3 修改 bin/system.properties 5.4 启动执行机 …

记录el-select+el-tree复选框,支持模糊查询,懒加载,树父子节点不关联,不全选

需求&#xff1a;一个机构下拉菜单&#xff0c;一个人员下拉菜单&#xff0c;默认带入当前登录用户的机构和人员。机构下拉菜单为两个接口&#xff0c;模糊查询为一个接口不包含懒加载&#xff0c;默认非模糊查询情况下为一个接口&#xff0c;点击节点懒加载。机构下拉菜单数据…

NACHI机器人虚拟示教器报I2101异常

前言 机器人示教器报&#xff1a;I2101 异常停止按钮或外部停止信号被输入 无法再示教模式下进行程序的运行&#xff01; 解决方法 结果 最后测试可以正常的运行程序

细说DMD芯片信号-DLP3

1&#xff0c; Block diagram 2. 信号介绍 2.1, LS interface&#xff1a; LD_Data_P/N(i), LD_CLK_P/N(i), LS_RDATA_A_BIST(O) 2.2, 视频信号: HSSI(High speed serial interface) High speed Differential Data pair lan A0~7 P/N, High speed Differential Clock A High…

如何使用人工智能优化 DevOps?

DevOps 和人工智能密不可分&#xff0c;影响着各种业务。DevOps 可以加快产品开发速度并简化现有部署的维护&#xff0c;而 AI 则可以改变整个系统的功能。DevOps团队可以依靠人工智能和机器学习来进行数据集成、测试、评估和发布系统。更重要的是&#xff0c;人工智能和机器学…

uniapp 微信小程序跳转至其他小程序

一、背景&#xff1a; 需要在目前的小程序中跳转到另一个小程序&#xff0c;跳转的目标小程序需要已经发布上线了 二、具体实现 使用uni.navigateToMiniProgram打开另一个小程序 官网指引&#x1f449;&#xff1a;uni.navigateToMiniProgram(OBJECT) | uni-app官网 <t…

IDEA中明明代码没有报错,运行也不报错,但是代码却爆红了,重启idea,重启电脑,重新加载Maven都没有用

报错示图&#xff1a; 报错类是存在的 我的解决办法是修改类名&#xff0c;修改类名时会有提示&#xff0c;如下图&#xff1a; 然后点击报错的地方可以看到是哪些位置引用了 改回正确的类名 正常显示

酚醛胶面建筑模板 — 广西厂家直销,质保可靠

在现代建筑行业中&#xff0c;选择高质量的建筑板材对于确保施工质量和工程安全至关重要。广西厂家直销的酚醛胶面建筑板&#xff0c;以其卓越的质量和可靠的质保&#xff0c;成为了建筑行业的优选材料。 产品特性 卓越的耐候性&#xff1a;我们的酚醛胶面建筑板采用高品质酚醛…

Keras实现seq2seq

概述 Seq2Seq是一种深度学习模型&#xff0c;主要用于处理序列到序列的转换问题&#xff0c;如机器翻译、对话生成等。该模型主要由两个循环神经网络&#xff08;RNN&#xff09;组成&#xff0c;一个是编码器&#xff08;Encoder&#xff09;&#xff0c;另一个是解码器…

MC-4/11/10/400​什么是电机驱动器。​

MC-4/11/10/400​什么是电机驱动器。​ 首先&#xff0c;我们先来了解以下两个主题&#xff0c;这会帮助我们了解什么是电机驱动器。 电机驱动器IC的作用 电机驱动器IC与电机设备之间的关系 电机驱动器的作用 用来使电机旋转&#xff08;驱动电机&#xff09;的集成电路&…

R语言【paleobioDB】——pbdb_collections():通过参数选择,返回多个采集号的基本信息

Package paleobioDB version 0.7.0 paleobioDB 包在2020年已经停止更新&#xff0c;该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后&#xff0c;执行本地安装。 Usage pbdb_collections (...) Arguments 参数【...…

云防护概念及云防护作用

云防护是什么 云防护是一种网络安全技术&#xff0c;旨在保护云计算环境中的数据和系统免受恶意攻击和未授权访问。 云防护适用场景 一切http.https.tcp协议&#xff0c;如游戏、电商、金融、物联网等APP PC 网站。 云防护的主要作用 云防护的主要作用是通过搭规模庞大的云防…

STM32存储左右互搏 SPI总线读写FRAM MB85RS2M

STM32存储左右互搏 SPI总线读写FRAM MB85RS2M 在中低容量存储领域&#xff0c;除了FLASH的使用&#xff0c;&#xff0c;还有铁电存储器FRAM的使用&#xff0c;相对于FLASH&#xff0c;FRAM写操作时不需要预擦除&#xff0c;所以执行写操作时可以达到更高的速度&#xff0c;其…