Qt中纯C++项目发布为dll的方法(超详细步骤)

目录

  • 一般创建方法
  • 导出普通函数的方法&调用方法
  • 导出类及其成员函数的方法&调用方法

众所周知,我们可以将C++项目中的类以及函数导出,形成 .dll 文件,以供其他程序使用,下面将说明Qt环境下的使用方法。

首先创建共享库,步骤如下:

 

 

下一步会出现类对话框等等,不用管它,直接点击创建即可,稍后再将类都删了。

创建好以后你会发现有一个包含global的头文件,这个文件中定义了__declspec(dllexport)、__declspec(dllimport)等,也可以删掉(如果要按照下面的方法的话,删掉即可)。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

接下来还有重要的一步,请在.pro文件中,加入

CONFIG += dll //即使你的代码中写成了 CONFIG += staticlib,也要改过来

接下来就开始我们具体的的创建方法吧!

按照导出dll的的操作划分,有两种模式:

  • 导出普通方法(导出后可静态调用,也可动态调用)

首先是头文件内容:

头文件:
在方法声明时,前面加上__declspec(dllimport),也可用#define定义,看代码:
//为了和将来用到的程序中公用一个头文件,创建dll时用到的是__declspec(dllexport),而使用dll时用到__declspec(dllimport),完全可以各自写一下
#define TESTDLLSHARED_EXPORT __declspec(dllexport)
#ifdef TESTDLLSHARED_EXPORT
#else
#define TESTDLLSHARED_EXPORT __declspec(dllimport)
#endif//下面我要定义4个普通函数:
TESTDLLSHARED_EXPORT int test1();TESTDLLSHARED_EXPORT int test2(void);TESTDLLSHARED_EXPORT int test3(int a);TESTDLLSHARED_EXPORT int test4(int a,int b);

然后在对应的cpp源文件中实现test1、test2、test3、test4这几个方法(为了简单,我只输出了一句话):

.cpp源文件://记得加上上面的头文件
//记得加上iostream头文件,不然cout不能用int test1()
{std::cout<<"test1"<<std::endl;
}int test2(void)
{std::cout<<"test2"<<std::endl;
}int test3(int a)
{std::cout<<"test3"<<std::endl;
}int test4(int a,int b)
{std::cout<<"test4"<<std::endl;
}

接下来就可以创建了,创建成功后(创建失败请仔细检查,代码已验证过),你会在你的项目输出目录下找到一个和项目名称一致的.dll文件。

OK!接下来我们来使用这个dll:

使用dll时有两种调用方法,一种是静态调用,一种是动态调用。

  • 静态调用

首先,创建一个常规的C++项目,将上面生成.dll复制到你的项目输出目录中(也就是和.exe文件在一起);

接下来,打开常规C++项目中的.pro文件,加入详细的.dll文件地址,格式如下

LIBS += 项目输出路径\dll文件全称

如我的就是

LIBS += D:\Desktop\Go\C++learnProgram\Qt\build-test_dll-Qt-Release\release\HpTickDll.dll
D:\Desktop\Go\C++learnProgram\Qt\build-test_dll-Qt-Release\release是我的项目输出路径,HpTickDll.dll是我的dll文件,使用时改动一下就好

接下来,将创建.dll文件时的头文件复制到当前项目路径下,并添加到项目中,注意:如果你没有按照我上面的#define条件定义方式,请重新写__declspec(dllimport)。

接下来,在.cpp文件中包含该头文件,就可以尽情地使用之前的函数了,如直接用test1()等等,就和平时编写一样的。

  • 动态调用

!!!特别注意:我们在创建时没有用到extern "C",也没有用到.def 文件保持函数名不变(尝试了很多次也不会用.def文件,会的欢迎留言),因此动态调用时函数名要改!因为编译器已经将函数名改了!

So,你一定会问我们怎么知道dll中的函数名变成啥了?不要着急,网上直接搜“.dll查看器”,遍地都是,下载下来后,选择我们刚才的.dll文件就可以看了,下面是我们的这几个函数test1、test2、test3、test4的新名称(你的可能和我的不一样哦):

请注意看红色框中的部分(不要管其他的,我的文件里面还有其他东西),这就是四个函数在.dll文件中的名称,我小小地猜测了一下,后面的v代表参数为void类型,i的个数代表int类型参数的个数,前面的字母就不太清楚了(注意:参数个数并未正确列出,不过我们只需要正确的函数名,不影响)。

OK!这就好办了!看步骤:

同样是创建一个常规C++项目,不同的是.pro文件中不用加“LIBS += 项目输出路径\dll文件全称”这句话了。

接下来在.cpp文件中写主代码(不用添加之前的头文件):

#include <iostream>
#include <windows.h>int main()
{//首先定义函数指针,用来接收不同参数的函数typedef int (CALLBACK *Fucv)();typedef int (CALLBACK *Fuci)(int);typedef int (CALLBACK *Fucii)(int,int);//获得.dll文件的句柄,需要头文件windows.h的支持HINSTANCE hdll=LoadLibrary(L"testDll.dll");     //L指宽字符串,若不写L,则会出现错误,详情请自查//注意这里要用.dll文件中的函数名Fucv t1=(Fucv)GetProcAddress(hdll,"_Z5test1v");Fucv t2=(Fucv)GetProcAddress(hdll,"_Z5test2v");Fuci t3=(Fuci)GetProcAddress(hdll,"_Z5test3i");Fucii t4=(Fucii)GetProcAddress(hdll,"_Z5test4ii");//现在的t1就执行的test1的功能,以此类推t1();t2();t3(1);t4(1,2);FreeLibrary(hdll);return 0;
}

以上就是普通函数创建.dll和使用.dll的方法,看起来动态调用是不是很麻烦?但它有许多优点(请自查),而且据说这里的函数名可以利用.def文件实现不改变名称,省去好多麻烦,但是我尝试了各种方法,如在.pro中利用DEF_FILE添加.def文件还是不行55555,会的可以留言哦!

  • 导出类及其成员函数(导出后可静态调用。暂时不会动态调用,某些书上说类不支持动态调用,网上有说在类中写一个方法返回类对象,但是个人认为这种做法是不对的,因为此时肯定是用自己定义的函数指针去定义这个返回类对象方法,不可能成功【已验证】,当然或许还有更好的方法,有知道的欢迎交流哈)

对于类的话,创建时:在class的后面,类名的前面加上定义的__declspec(dllexport);使用时,换成__declspec(dllimport),也可以参照前面的#define条件定义法。举例:

#define HPTICKDLLSHARED_EXPORT __declspec(dllexport)
#ifdef HPTICKDLLSHARED_EXPORT
#else
#define HPTICKDLLSHARED_EXPORT __declspec(dllimport)
#endifclass HPTICKDLLSHARED_EXPORT HpTickDll  //我在这里定义了类HpTickDll
{   
public:int  Start();                       //注意成员函数之前不用加HPTICKDLLSHARED_EXPORTint  GetTime();private:LARGE_INTEGER li;LONGLONG start, end, freq;int useTime;
};

静态调用的方法和普通函数一样,直接可以使用类及其成员函数(别忘了添加头文件),就不细说了。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(Qt实战项目视频教程+代码,C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

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

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

相关文章

印刷包装经营小程序商城的作用是什么

印刷包装业的市场需求度非常高&#xff0c;如礼品盒、标签、购物袋、企业宣传物料、周边等大小服务&#xff0c;线下各城市从业者与线上行业电商数量也很多。 然而随着线下竞争激烈、用户线上消费度提升&#xff0c;同时线上第三方平台入驻商家面临抽成/入驻费/流量费、难以打…

vtk简单介绍、渲染流程、简单示例

一、vtk简单介绍 Vtk&#xff08;visualization toolkit&#xff09;是一个开源的免费软件系统&#xff0c;主要用于三维计算机图形学、图像处理和可视化。 二、vtk渲染流程 流程图如下&#xff1a; 1.vtkSource 数据源 各个类型的图像原始数据。 2.vtkFilter 数据过滤器 …

多继承vs查看类结构

多继承里面的虚函数 类A有两个虚函数&#xff0c;类B重写了其中一个&#xff0c;类C重写了两个&#xff1b; 类C里面可以重写所有继承到的虚函数&#xff08;类A、类B里面的虚函数&#xff09; class A { public:virtual void init() { std::cout << "A init !&qu…

硬件成本节省60%,四川华迪基于OceanBase的健康大数据数仓建设实践

导语&#xff1a;本文为四川华迪数据计算平台使用 OceanBase 替代 Hadoop 的实践&#xff0c;验证了 OceanBase 在性能和存储成本方面的优势&#xff1a;节省了 60% 的硬件成本&#xff0c;并将运维工作大幅减少&#xff0c;从 Hadoop 海量组件中释放出来&#xff1b;一套系统处…

21天打卡掌握java基础操作

Java安装环境变量配置-day1 参考&#xff1a; https://www.runoob.com/w3cnote/windows10-java-setup.html 生成class文件 java21天打卡-day2 输入和输出 题目&#xff1a;设计一个程序&#xff0c;输入上次考试成绩&#xff08;int&#xff09;和本次考试成绩&#xff0…

如何用工业树莓派和MQTT平台打通OT和IT?

一、应用设备 OT端设备&#xff1a;步进电机&#xff0c;MODBUS TCP远程I/O模块&#xff0c;PLC设备 边缘侧设备&#xff1a;宏集工业树莓派&#xff1b; IT端设备&#xff1a;PC、安卓手机&#xff1b; IT端软件&#xff1a;宏集HiveMQ MQTT通信平台 二、原理 宏集工业树…

iOS 中,isa 指针

每个对象都有 isa 指针&#xff0c;指向对象所属的类。例如类 NSString 其实是类对象。 类对象产生于编译期&#xff0c;单例。 类对象有 isa 指针指向对应元类&#xff0c;元类&#xff08;metaclass&#xff09;中保存了创建类对象以及类方法所需的所有信息。 struct objc_…

react实现一维表格、键值对数据表格key value表格

UI画的需求很抽象&#xff0c;直接把数据铺开&#xff0c;不能直接用antd组件了 上一行是name&#xff0c;下一行是value&#xff0c;总数不定&#xff0c;最后前端还要显示求和 class OneDimensionTable extends React.Component { render() {const { data } this.props;le…

Linux安装node_exporter使用grafana进行服务器监控

文章目录 linux安装node_exporter修改node_exporter端口服务器安装grafana服务器安装prometheus将linux的noe_exporter配置到prometheus配置文件中导入linux服务器的模板,id: 16098常用exporter安装下载 linux安装node_exporter 要在CentOS 7.6.1810 (Core)上安装node_exporte…

网安顶刊IEEE Transactions on Dependable and Secure Computing

安全顶刊论文列表 写在最前面IEEE Transactions on Dependable and Secure ComputingTable of Contents&#xff08;March-April 2023&#xff09;Volume 20, Issue 2Table of Contents&#xff08;Sept.-Oct. 2023&#xff09;Volume 20, Issue 5 写在最前面 为了给自己找论文…

2023_Spark_实验十九:SparkStreaming入门案例

SparkStreaming入门案例 一、准备工作 二、任务分析 三、官网案例 四、开发NetWordCount 一、准备工作 实验环境&#xff1a;netcat 安装nc&#xff1a;yum install -y nc 二、任务分析 将nc作为服务器端&#xff0c;用户产生数据&#xff1b;启动sparkstreaming案例中的客户端…

NIO IN:技术蔚来的首次「大阅兵」

宝山&#xff0c;上海第一钢铁厂旧址。 上周&#xff0c;蔚来在这里点亮金色炉台&#xff0c;2500 立方米高炉&#xff0c;浓重的工业气质与古典凝重的光影交织&#xff0c;蔚来 NIO IN 用科技的进步呼应那个火红的年代。 这是蔚来第一次开科技发布会&#xff0c;为了全方位展…

通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境

&#x1f525;博客主页&#xff1a; 小羊失眠啦 &#x1f516;系列专栏&#xff1a; C语言 、Cpolar、Linux ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 …

通讯协议学习之路:RS485协议理论

通讯协议之路主要分为两部分&#xff0c;第一部分从理论上面讲解各类协议的通讯原理以及通讯格式&#xff0c;第二部分从具体运用上讲解各类通讯协议的具体应用方法。 后续文章会同时发表在个人博客(jason1016.club)、CSDN&#xff1b;视频会发布在bilibili(UID:399951374) 序&…

HTTP 协议的基本格式(部分)

要想了解HTTP&#xff0c;得先知道什么是HTTP&#xff0c;那么HTTP是什么呢&#xff1f;HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的 应用层协议。那什么是超文本呢&#xff1f;那就是除了文本&#xff0c;还有图片&#xff0c;声音&#xff0c;视频等。 …

『C++成长记』C++入门——命名空间缺省参数

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、C的认识 &#x1f4d2;1.1什么是C &#x1f4d2;1.2C的发展 二、C关键字 三…

论文阅读之《Kindling the Darkness: A Practical Low-light Image Enhancer》

目录 摘要 介绍 已有方法回顾 普通方法 基于亮度的方法 基于深度学习的方法 基于图像去噪的方法 提出的方法 2.1 Layer Decomposition Net 2.2 Reflectance Restoration Net 2.3 Illumination Adjustment Net 实验结果 总结 Kindling the Darkness: A Practical L…

轮转数组------题解报告

题目&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题解&#xff1a; 如果直接暴力双循环会时间超限&#xff0c;所以我选择了一个空间复杂度比较高的方法。直接再创建一个数组&#xff0c;然后对应位置替换&#xff0c;最后把值赋给原…

Spring framework Day24:定时任务

前言 在我们的日常生活和工作中&#xff0c;时间管理是一项至关重要的技能。随着各种复杂任务的增加和时间压力的不断增加&#xff0c;如何更好地分配和利用时间成为了一项迫切需要解决的问题。在这样的背景下&#xff0c;定时任务成为了一种非常有效的解决方案。 定时任务&a…

Kubernetes技术与架构-服务

从软件系统架构设计分层的角度看&#xff0c;Kubernetes的Service是基于Pod的上层&#xff0c;业务应用部署在Pod中&#xff0c;使用Service绑定Pod部署的应用&#xff0c;Service可以对外或者对上层提供服务&#xff0c;当Pod集群在系统调度的过程中发生弹性伸缩的时候&#x…