文章目录

  • 一、创建动态库dll (方法一)
    • 1 生成C++ 动态库dll
      • 1.1 创建项目MyDLL
      • 1.2 编写.h 和 .cpp文件
      • 1.3 设置 及 生成 DLL
    • 2 调用 C++ 动态库dll
      • 2.1 创建C++ 空项目DLLtest
      • 2.2 动态库配置 及代码调用测试
    • 3 实际项目中的使用技巧
      • 3.1 设置dll输出路径
      • 3.2 设置头文件引入路径
      • 3.3 改进后 测试
    • 4 __cplusplus 解释
    • 5 完整代码.h文件、.cpp 文件
    • 6 完整项目文件下载

创建动态库dll项目有两种方法;

  • 1.VS创建 C++ 空项目,然后在项目属性中将项目 配置类型 改为 动态库(.dll),规范性要求不高,且创建方式熟悉。这种方法也可以用,但有时这种方法生成的dll在项目调用中, 会出现各种奇怪的错误。 故,此法 多用于新手测试,正式项目慎用。
  • 2.VS创建 动态链接库(DLL) 项目, 更安全、正规,代码要求更规范。

一、创建动态库dll (方法一)

1 生成C++ 动态库dll

为了验证效果,使用三种方法导出函数:

  • //导出函数
  • //导出类
  • //以C方式导出函数
创建动态库d11:1.VS创建动态链接库(DLL) MyDLL:编写.h和.cpp文件在.h文件中宏定义导出图数2.生成dll文件:右键项目-->属性-->配置类型-->动态库( .dll)以Debug x64 生成解决方案

1.1 创建项目MyDLL

1.VS创建C++ 空项目MyDLL:
在这里插入图片描述
在这里插入图片描述

1.2 编写.h 和 .cpp文件

添加 mathTest.hmathTest.cpp文件
在这里插入图片描述
mathTest.h 文件

#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定义导出:
#ifndef MATHTEST_ //如果没有定义 MATHTEST_,就定义MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //导出
#else
#define MATHTEST_API __declspec(dllimport) //导入
#endif//导出函数
MATHTEST_API int add(int a, int b);//加法
MATHTEST_API int subtract(int a, int b);//减法//导出类
class MATHTEST_API mathTest
{public:int multiply(int a, int b);//乘法int divide(int a, int b);//除法
};//以C方式导出函数
//extern "C",告诉编译器这里是C语言代码//为了使自己建的库可以在 C/C++ 通用调用,使用 __cplusplus ,
//当C++调用代码时,__cplusplus 值为1,声明函数外面就加了一层“extern "C" {}”;
//当C 调用代码时,__cplusplus 值为0,就相当于没有“extern "C" {}”;#ifdef __cplusplus 
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);//加法MATHTEST_API int Csubtract(int a, int b);//减法
#ifdef __cplusplus
}
#endif#endif

mathTest.cpp文件

#include "mathTest.h"/*创建动态库d11:1.VS创建C++ 空项目MyDLL:编写.h和.cpp文件在.h文件中宏定义导出图数2.生成dll文件:右键项目-->属性-->配置类型-->动态库( .dll)以Debug x64 生成解决方案
*///导出函数
int add(int a, int b)//加法
{return a + b;
}
int subtract(int a, int b)//减法
{return a - b;
}//导出类
int mathTest::multiply(int a, int b)//乘法
{return a * b;
}int mathTest::divide(int a, int b)//除法
{return a / b;
}//以C方式导出函数
int Cadd(int a, int b)//加法
{return a + b;
}int Csubtract(int a, int b)//减法
{return a - b;
}

1.3 设置 及 生成 DLL

右键项目–>属性–>配置类型–>动态库( .dll)
在这里插入图片描述
右键项目–>生成 (如修改后,可以点重新生成)
在这里插入图片描述

在这里插入图片描述

查看 生成的DLL文件
在这里插入图片描述
查看DLL
在这里插入图片描述

注意是.E:\Test\MyDLL\x64\Debug,在工程同级目录下\x64\Debug下面

在这里插入图片描述

而不是 E:\Test\MyDLL\MyDLL\x64\Debug,而不是在.h同级目录的\x64\Debug下面(刚开始就在这里找,发现MyDLL.dll.recipe多了一个.recipe,迷糊了半天

在这里插入图片描述

2 调用 C++ 动态库dll

方法:

创建C++ 空项目DLLtest使用动态库d11:隐式调用:1..lib(MyDLL.lib).dll(MyDLL.d11).h(mathTest.h)文件放到工程目录下(DLLtest项目的.cpp同目录下)2.项目右键-- > 属性-->配置属性-->链接器-->输入->附加依项-- > 添加MyDLL.lib3.#include mathTest.h4.代码调用

2.1 创建C++ 空项目DLLtest

这里测试代码有两种建里新项目的方法:

  • 1可以直接在 "MyDLL”解决方案下 建创建C++ 空项目DLLtest;( 实际项目中dll项目和用户项目建立在同一个解决方案下,这样更方便代码修改与管理,在调试时 主项目代码还可以直接调试访问dll中的源代码,这样就更方便dll代码的调试优化等操作。)
  • 2 也单独建立一个项目方案;

这里为了方便,直接原来的解决方案上新增测试项目这样做的好处是如果测试之后dll代码有问题或功能达不到预期,可以方便随时修改dll的源代码。

右键 解决方案"MyDLL”->添加->新建项目;创建C++ 空项目DLLtest

在这里插入图片描述

在这里插入图片描述
可以看到,解决方案下有两个项目,“DLLtest”和“MyDLL
在这里插入图片描述
在DLLtest项目下添加,main.cpp文件
在这里插入图片描述

2.2 动态库配置 及代码调用测试

使用动态库d11:
隐式调用:

   隐式调用:1.把.lib(MyDLL.lib)、.dll(MyDLL.dll)、.h(mathTest.h)文件放到工程目录下(DLLtest项目的.cpp同目录下)2.项目右键-- > 属性-->配置属性-->链接器-->输入->附加依项-- > 添加MyDLL.lib3.#include mathTest.h4.代码调用

在这里插入图片描述
在我们的dll文件中分别设置了 导出函数、导出类成员函数、以C方式导出的函数,现在这三种函数都在main文件中调用测试。

完整代码

#include<iostream>
#include"mathTest.h"
using namespace std;/*
VS创建C++ 空项目DLLtest使用动态库d11:隐式调用:1.把.lib(MyDLL.lib)、.d11(MyDLL.d11)、.h(mathTest.h)文件放到工程目录下(DLLtest项目的.cpp同目录下)2.项目右键-- > 属性-->配置属性-->链接器-->输入->附加依项-- > 添加MyDLL.1b3.#include mathTest.h4.代码调用
*/int main()
{//调用dll 导出函数int sum = add(10, 5);int sub = subtract(10, 5);//调用dll 导出类成员函数mathTest mathT; //实例化对象int mul = mathT.multiply(10, 5);int div = mathT.divide(10, 5);//调用dll 以C方式导出的函数int Csum = Cadd(10, 5);int Csub = Csubtract(10, 5);cout << "我的动态库dll调用: "<< endl;cout << "add(10,5) = " << sum << endl<< "subtract(10,5) = " << sub << endl<< "multiply(10,5) = " << mul << endl<< "divide(10,5) = " << div << endl<< "Cadd(10,5) = " << Csum << endl<< "Csubtract(10,5) = " << Csub << endl;return 0;
}

运行测试,报错。是因为 当前启动项为“MyDLL”,需要将启动项设为 “DLLtest”。
在这里插入图片描述
右键 “DLLtest”,选择“设为启动项”
在这里插入图片描述

在这里插入图片描述
导出函数、导出类成员函数、以C方式导出的函数,现在这三种函数都用结果都输出了,说明这三种dll导出函数方式都有,但我最常用的是 以C方式导出的函 ,这中通用个,避免出错。

在这里插入图片描述

3 实际项目中的使用技巧

自动路径(.dll、.lib、.h复制到 测试项目的.cpp目录下,太麻烦)

3.1 设置dll输出路径

直接将dll生成文件,的生路径设为 “DLLtest”项目下的.cpp路径;

打开项目,观察路径位置关系
在这里插入图片描述

为了是的路径通用,这里使用相对路径 ../DLLtest/,并且将 MyDLL设为启动项,方便后面dll重新生成
在这里插入图片描述
重新生成dll,可见新的dll文件已经 生成在DLLtest项目下面了
在这里插入图片描述
在这里插入图片描述

3.2 设置头文件引入路径

将DLLtest设为启动项;
设置DLLtest项目的 附加包含目录为 …/MyDLL/这样DLLtest项目就可以访问 mathTest.h 文件了。
在这里插入图片描述

3.3 改进后 测试

在这里插入图片描述

注意:既然新的dll生成路径已经更改到 “DLLtest”项目下的.cpp路径,那么第一次在 MyDLL\x64\Debug\路径下生成的生成的dll最好删掉,

不然两个路径同时存在dll,调用时会产生混淆,当两个路径下的dll代码源文件完全一样时,似乎并没有影响。一旦新的dll代码修改了,这时两个路径下dll内容不一致,调用运行时就会出错。

所以下面的4文件删掉。
在这里插入图片描述

4 __cplusplus 解释

为了使自己建的 C/C++ 库可 都可以通用

使用 __cplusplus

  • 当C++代码时,__cplusplus 值为1;
  • 当C 代码时,__cplusplus 值为0;
#ifdef __cplusplus 
.
.
.
#endif

下面是完整的.h文件

//#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定义导出:
#ifndef MATHTEST_ //如果没有定义 MATHTEST_,就定义MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //导出
#else
#define MATHTEST_API __declspec(dllimport) //导入
#endif//动态链接MATHTEST_API库//以C语言的方式导出函数
//extern "C",告诉编译器这里是C语言代码#ifdef __cplusplus 
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//减法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法#ifdef __cplusplus
}
#endif#endif

当C++ 代码时,__cplusplus 值为1,那么源代码对应部分 等价于

extern "C"
{MATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//减法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法
}
#endif

当C 代码时,__cplusplus 值为0,那么源代码 对应部分 等价于;
#ifdef __cplusplus#endif 部分是没有执行的

	MATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//减法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法

5 完整代码.h文件、.cpp 文件

为了统一规范,同时使用“以C语言的方式导出函数”

mathTest.h文件

#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H//宏定义导出:
#ifndef MATHTEST_ //如果没有定义 MATHTEST_,就定义MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //导出
#else
#define MATHTEST_API __declspec(dllimport) //导入
#endif//以C方式导出函数
//extern "C",告诉编译器这里是C语言代码//为了使自己建的库可以在 C/C++ 通用调用,使用 __cplusplus ,
//当C++调用代码时,__cplusplus 值为1,声明函数外面就加了一层“extern "C" {}”;
//当C 调用代码时,__cplusplus 值为0,就相当于没有“extern "C" {}”;#ifdef __cplusplus 
extern "C"
{
#endifMATHTEST_API int Cadd(int a, int b);     //加法MATHTEST_API int Csubtract(int a, int b);//减法MATHTEST_API int Cmultiply(int a, int b); //乘法MATHTEST_API int Cdivide(int a, int b);   //除法#ifdef __cplusplus
}
#endif#endif

mathTest.cpp文件

#include<iostream>
#include"mathTest.h"
using namespace std;/*
VS创建C++ 空项目DLLtest使用动态库d11:隐式调用:1.把.lib(MyDLL.lib)、.d11(MyDLL.d11)、.h(mathTest.h)文件放到工程目录下(DLLtest项目的.cpp同目录下)2.项目右键-- > 属性-->配置属性-->链接器-->输入->附加依项-- > 添加MyDLL.1b3.#include mathTest.h4.代码调用
*/int main()
{//调用以C方式导出的函数int Csum = Cadd(10, 5);int Csub = Csubtract(10, 5);int Cmul = Cmultiply(10, 5);int Cdiv = Cdivide(10, 5);cout << "我的动态库dll调用: " << endl;cout << "Cadd(10,5) = " << Csum << endl<< "Csubtract(10,5) = " << Csub << endl<< "Cmultiply(10,5) = " << Cmul << endl<< "Cdivide(10,5) = " << Cdiv << endl;return 0;
}

6 完整项目文件下载

完整项目工程文件,下载后可直接编译运行
在这里插入图片描述

代码下载:C++ 生成动态库.dll 及 C++调用DLL

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

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

相关文章

kettle插件-kettle http client plus插件,轻松解决https接口无法调用文件流下载问题

场景&#xff1a;小伙伴在使用kettle调用https接口过程中无法正常调用&#xff0c;程序出错问题&#xff0c;今天演示下用自研插件轻松解决这个问题。1、使用openssl 生成自签名证书openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 3652、使用…

C#中的除法

在C#中&#xff0c;除法操作可以通过使用 / 运算符执行。这个运算符可以进行整数除法或浮点除法&#xff0c;这取决于操作数的类型。整数除法当两个整数相除时&#xff0c;结果将自动向下取整到最接近的整数。这意味着结果是一个整数&#xff0c;而不是小数。int a 10; int b …

PPT文件密码解密工具推荐:Tenorshare PassFab for PPT绿色免安装一键解除密码限制,附详细教程和下载地址

前段时间&#xff0c;我帮朋友做一个商业演示的 PPT&#xff0c;为了防止文件被误操作或者内容泄露&#xff0c;我给 PPT 设置了密码。结果等朋友来拿文件的时候&#xff0c;我居然把密码忘得干干净净&#xff0c;这下可把我俩都急坏了。朋友那边马上就要用这个 PPT 去参加重要…

【数据结构】二叉树接口实现指南:递归方法的高效运用 (附经典算法OJ)

文章目录 1、前置说明 1、定义二叉树结点结构 2、创建新节点 3、手动创建二叉树 2、二叉树的遍历 1、前序&#xff0c;中序和后序遍历 1.1、二叉树前序遍历 1.2、二叉树中序遍历 1.3、二叉树后序遍历 2、二叉树层序遍历 3、二叉树的基础操作 1、二叉树节点总数 2、…

自动驾驶控制算法——LQR控制算法

自动驾驶控制算法——LQR控制算法 文章目录自动驾驶控制算法——LQR控制算法**一、LQR 是什么&#xff1f;**二、LQR 原理2.1 线性状态空间模型 (State–Space Model)2.2 二次型性能指标 JJJ2.3 代数黎卡提方程 (ARE)2.4 特点总结2.5 一句话总结 LQR 原理&#xff1a;2.5.1 场景…

Jotai:React轻量级原子化状态管理,告别重渲染困扰

简介 Jotai 是一个为 React 提供的原子化状态管理库&#xff0c;采用自下而上的方法来进行状态管理。Jotai 受 Recoil 启发&#xff0c;通过组合原子来构建状态&#xff0c;并且渲染基于原子依赖性进行优化。这解决了 React 上下文的额外重新渲染问题&#xff0c;并消除了对 m…

C语言数据结构(7)贪吃蛇项目2.贪吃蛇项目实现

8. 核心逻辑实现分析 8.1 游戏主逻辑 程序开始就设置程序支持本地模式&#xff0c;然后进入程序的主逻辑。 主逻辑分为3个过程&#xff1a; • 游戏开始&#xff08;GameStart&#xff09;完成游戏的初始化。 • 游戏运行&#xff08;GameRun&#xff09;完成游戏运行逻辑的…

知识蒸馏 - 最小化KL散度与最小化交叉熵是完全等价的

知识蒸馏 - 最小化KL散度与最小化交叉熵是完全等价的 flyfish KL散度与交叉熵的数学关系 对于两个概率分布 PPP&#xff08;真实分布&#xff09;和 QQQ&#xff08;模型预测分布&#xff09;&#xff0c;KL散度的定义是&#xff1a; DKL(P∥Q)∑xP(x)log⁡(P(x)Q(x)) D_{KL}(P…

设计心得——网络包的处理

一、介绍 在程序的开发中&#xff0c;网络开发是一个重要的应用场景。毕竟这些年IT行业之所以火&#xff0c;主要还是互联网&#xff08;移动互联网&#xff09;带来的。网络开发&#xff0c;有各种平台、框架以及系统和库提供的API&#xff0c;如果说网络开发是一个特别复杂和…

sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)

目录 一、源码分析 1、index.php代码审计 2、login.php代码审计 3、java_implimentation函数 4、whitelist函数 5、SQL安全性分析 二、渗透实战 1、进入靶场 2、WAF探测 &#xff08;1&#xff09;触发WAF &#xff08;2&#xff09;绕过WAF 3、手工注入 &#xf…

【openlayers框架学习】九:openlayers中的交互类(select和draw)

文章目录openlayers进阶28 openlayers中的事件29 openlayers中select交互类的使用30 openlayers中select常见的配置选项31 openlayers中绘制交互类&#xff08;Draw&#xff09;openlayers进阶 28 openlayers中的事件 常用进行事件交互的对象&#xff1a;map\view\source29 o…

Java企业级应用性能优化实战

在企业级Java应用开发中,性能优化是确保系统稳定运行的关键因素。本文将从多个维度深入分析Java应用性能瓶颈,并提供实战优化方案。 🎯 性能优化核心领域 1. 对象操作性能优化 在企业应用中,对象拷贝是一个高频操作,特别是在分层架构中的DO、DTO、VO转换。选择合适的拷…

LLM Prompt与开源模型资源(3)如何写一个好的 Prompt

学习材料&#xff1a;https://www.hiascend.com/developer/courses/detail/1935520434893606913 &#xff08;3.5&#xff09;学习时长&#xff1a; 预计 60 分钟学习目的&#xff1a; 了解提示工程的定义与作用熟悉提示工程的关键技术相关概念掌握基于昇腾适配的大模型提示工程…

日志管理工具 ——ELK Stack

一、ELK Stack 概述1.1 核心组件ELK Stack&#xff08;现更名为 Elastic Stack&#xff09;是一套开源的日志收集、存储、分析和可视化平台&#xff0c;由三个核心组件构成&#xff1a;Elasticsearch&#xff1a;分布式搜索引擎&#xff0c;负责日志数据的存储、索引和快速查询…

SpringAI:AI工程应用框架新选择

Spring AI 是一个用于 AI 工程的应用框架 Spring AI 是一个用于 AI 工程的应用框架。其目标是将可移植性和模块化设计等 Spring 生态系统设计原则应用于 AI 领域,并推广使用 POJO 作为应用程序的构建块到 AI 领域。 Spring AI 的核心是解决 AI 集成的基本挑战:将企业数据和…

Kettle 开源ETL数据迁移工具从入门到实战

ETL&#xff08;Extract, Transform, Load&#xff09;工具是用于数据抽取、转换和加载的软件工具&#xff0c;用于支持数据仓库和数据集成过程。Kettle作为传统的ETL工具是纯 java 开发的开源的 ETL工具&#xff0c;用于数据库间的数据迁移 。可以在 Linux、windows、unix 中运…

Maven中的bom和父依赖

maven最全避坑指南写完后&#xff0c;发现自己对于bom和父pom的理解还是不够深入&#xff0c;特此转载DeepSeek的回答&#xff0c;和大家一起学习了。 在 Maven 的依赖管理中&#xff0c;父 POM (Parent POM) 和 BOM (Bill of Materials) 都是用于实现集中化管理和控制的核心机…

Python 操作 Word 文档:主流库对比与选择指南

在办公自动化、报告生成、数据处理等领域&#xff0c;利用 Python 程序化地创建、读取或修改 Microsoft Word 文档 (.docx 格式) 是一项非常实用的技能。Python 生态中有多个优秀的库可以完成这项任务&#xff0c;但它们各有侧重和优缺点。选择哪一个“最好用”&#xff0c;关键…

怎么修改论文格式呢?提供一份论文格式模板

注!!!本文内容是作者自己整理的一份模板,仅供参考,各位如何修改,还需要看学校的要求。 一、参考文献 1、有一定数量的近几年参考文献、不宜过多中文文献 英文期刊模板 [1] Taesoo K, Sooyoung K, Kyunghan L, et al. Special issue on 6G and satellite communication…

MVC 发布

MVC 发布 引言 MVC(Model-View-Controller)模式是一种广泛应用于软件开发的架构模式。它将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。这种模式不仅提高了代码的可维护性和可扩展性,而且使得开发者可以更加专注于各个组件的开发。本文…