Qt--动态链接库的创建和使用

写在前面

在Qt的实际开发中,免不了使用和创建动态链接库,因此熟悉Qt中动态链接库的创建和使用对后续的库开发或使用是非常用必要的。

在之前的文章https://blog.csdn.net/SNAKEpc12138/article/details/126189926?spm=1001.2014.3001.5501中已经对导入导出的声明有过详细介绍了,通过Qt向导创建的动态库项目也会带上这些声明,因此这里不再赘述。

开发环境;
Qt:5.15.2
Qt Creator:10.0.2

动态链接库的创建

打开Qt Creator,创建项目 -> 选择 库 -> C++ Library
1
自定义项目名称和存放路径:
2
默认使用qmake构建:
3
库类型默认:
4
无需翻译文件:
5

选择构建套件,这里使用Qt 5.15.2 MSVC2019_64bit
6
最后的总览;
7
生成后可以看到向导自动生成了如下文件:
8

.pro文件内容如下;
9
qtdlltest.h头文件中定义了导出类信息,内容如下;
10
QtDllTest_global.h头文件主要通过上面.pro文件中定义的QTDLLTEST_LIBRARY宏,来区别导入和导出声明:
11

最后是导出类的实现:
12
编译运行可以在生成路径下生成了一个dll:
13

这里添加一个成员函数,以便后面使用:

14
15
重新生成,同样可以使用dumpbin工具查看导出信息:

如何配置使用VS提供的dumpbin工具可参考:https://blog.csdn.net/SNAKEpc12138/article/details/126109249?spm=1001.2014.3001.5501

16

虽然发生了名字改编,也不影响我们在Qt项目中使用,可参考:https://blog.csdn.net/SNAKEpc12138/article/details/126235303?spm=1001.2014.3001.5501

动态链接库的使用

在其他项目中使用Qt动态链接库,需用到以下文件:
①导入/导出声明全局文件。例上面的:QtDllTest_global.h,若未使用全局文件,则无需。
②导出声明头文件。例上面的:qtdlltest.h
③lib 和 dll。例生成目录下的:QtDllTest.lib 和 QtDllTest.dll

下面再创建一个新的项目来使用上面生成dll, 这里使用一个简单Qt控制台程序示例。

首先将需要的文件拷贝到使用项目的目录下,头文件和.lib文件可需防止.pro文件所在目录下(因为要在代码中引用),.dll文件放在生成目录下。

这里习惯将头文件放在.pro目录下的include文件夹中,将.lib文件放在.pro目录下的lib文件夹中:
17
将.dll文件放在项目的生成目录下,不知道项目的生成目录,可在Qt Creator左侧的项目界面中查看:
18
19

文件放置妥当后,即可开始使用动态链接库了,这里也可分为静态加载和动态加载两种方式。

静态加载

在使用项目的.pro文件中添加附加库目录和导入.lib :
20
补充:$$PWD为.pro文件所在目录。

在代码中使用:
21

注意:上面.pro文件中的LIBS += $$PWD/lib/QtDllTest,有的版本无需加上.lib后缀,而有些版本则需要加上.lib后缀。

当出现以下报错(**LNK1181: 无法打开输入文件: ***\库名称.obj)时,则需要加上.lib后缀:
22

动态加载

因为动态加载只能调用动态库的导出函数,而且必须是extern"C"的,调用不了类,因此这里需要重新在dll项目中添加一个全局函数:
23
24

重新生成后更新qtdlltest.h、QtDllTest.lib、QtDllTest.dll到使用项目中!

然后即可在使用项目中动态加载:

#include <QCoreApplication>
//#include "qtdlltest.h"

#include <QLibrary>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

//    QtDllTest dll;
//    dll.printFromDll();

    QLibrary lib("QtDllTest.dll");
    if (!lib.load())
    {
        qDebug() << "Failed to Load Library!";
        qDebug() << lib.errorString();
        return 0;
    }

    typedef void (*pFunc)();
    pFunc f = lib.resolve("globalPrint");
    if (f)
    {
        f();
    }
    else
    {
        qDebug() << "Failed to get function!";
    }

    return a.exec();
}

输出如下:
25

总结

综上,简单介绍了Qt动态链接库的创建和使用,使用时也分别示例的静态加载和动态加载的区别。

需要注意的是:
①静态加载添加.lib文件时,因Qt版本不同,可能需要加上.lib后缀。
②动态加载时,只能加载extern"C"的全局函数,不能加载类,因此在Qt中,一般不会使用这种加载方式。

若想使用动态加载,且用到导出类时,Qt中提供了QPluginLoader插件类来实现,这个会在之后的文章中详细介绍。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法与数据结构-跳表

文章目录 什么是跳表跳表的时间复杂度跳表的空间复杂度如何高效的插入和删除跳表索引动态更新代码示例 什么是跳表 对于一个单链表来讲&#xff0c;即便链表中存储的数据是有序的&#xff0c;如果我们要想在其中查找某个数据&#xff0c;也只能从头到尾遍历链表。这样查找效率…

leetcode 746. 使用最小花费爬楼梯

2023.8.8 昨天爽玩一天&#xff0c;在家就是舒服。 今天继续刷动态规划题。 动态规划题最重要的就是搞清楚dp[i] 的定义&#xff0c;本题dp[i] 的含义是&#xff1a;到达第i层&#xff0c;所需的最小花费。 那么由于起始台阶可以是0或者1&#xff0c;那么dp[0]和dp[1]都初始化…

[保研/考研机试] KY30 进制转换-大整数转二进制 清华大学复试上机题 C++实现

描述 将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。 输入描述&#xff1a; 多组数据&#xff0c;每行为一个长度不超过30位的十进制非负整数。 &#xff08;注意是10进制数字的个数可能有30个&#xff0c;而非30bits的整数&#xff09; 输出描述&#xff…

SolidUI社区-提示词链式思考(CoT)

背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一个创新的项目&#xff0c;旨在将自然语言处理&#xff08;NLP&#xff09;与计算机图形学相…

C语言:打开调用堆栈

第一步&#xff1a;打断点 第二步&#xff1a;FnF5 第三步&#xff1a;按如图找到调用堆栈

Android模板设计模式之 - 构建整个应用的BaseActivity

1. 模式介绍 模式的定义 定义一个操作中的算法的框架&#xff0c;而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 模式的使用场景 1.多个子类有公有的方法&#xff0c;并且逻辑基本相同时。 2.重要、复杂的算法&#xff0c;可…

Java基础入门篇——Java变量类型的转换和运算符(七)

目录 一、变量类型 1.1自动类型转换&#xff08;隐式转换&#xff09; 1.2 强制类型转换&#xff08;显式转换&#xff09; 1.3类型转换的其他情况 二、运算符 2.1算术运算符 2.2比较运算符 2.3逻辑运算符 2.4位运算符 三、总结 在Java中&#xff0c;变量类型的转换…

ubuntu python虚拟环境venv搭配systemd服务实战

文章目录 参考文章目录结构步骤安装venv查看python版本创建虚拟环境激活虚拟环境运行我们程序看缺少哪些依赖库&#xff0c;依次安装它们接下来我们配置python程序启动脚本&#xff0c;脚本中启动python程序前需先激活虚拟环境配置.service文件然后执行部署脚本&#xff0c;成功…

考研算法第40天:众数 【模拟,简单题】

题目 本题收获 又是一道比较简单的模拟题&#xff0c;就不说解题思路了&#xff0c;说一下中间遇到的问题吧&#xff0c;就是说cin输入它是碰到空格就停止输入的&#xff0c;详细的看下面这篇博客对于cin提取输入流遇到空格的问题_while(cin) 空格_就是那个党伟的博客-CSDN博…

JVM 调优实例

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ JVM提供了多种垃圾回收器&#xff0c;可以根据应用程序的需求选择最适合的垃圾回收器。例如&#xff0c;如果应用程序需要更快的响应时间&#xff0c;可以选择并行垃圾回收…

Hello,SpringBoot!

一、回顾什么是Spring Spring是一个开源框架&#xff0c;2003 年兴起的一个轻量级的Java 开发框架&#xff0c;作者&#xff1a;Rod Johnson Spring是为了解决企业级应用开发的复杂性而创建的&#xff0c;简化开发。 Spring是如何简化Java开发的 为了降低Java开发的复杂性…

模仿火星科技 基于cesium+ 贴地测量+可编辑

当您进入Cesium的编辑贴地测量世界&#xff0c;下面是一个详细的操作过程&#xff0c;帮助您顺利使用这些功能&#xff1a; 1. 创建提示窗&#xff1a; 启动Cesium应用&#xff0c;地图场景将打开&#xff0c;欢迎您进入编辑模式。在屏幕的一角&#xff0c;一个友好的提示窗将…

【在一个升序数组中插入一个数仍升序输出】

在一个升序数组中插入一个数仍升序输出 题目举例&#xff1a; 有一个升序数组nums&#xff0c;给一个数字data&#xff0c;将data插入数组nums中仍旧保证nums升序&#xff0c;返回数组中有效元素个数。 比如&#xff1a;nums[100] {1, 2, 3, 5, 6, 7, 8, 9} size 8 data 4 …

LabVIEW开发高压配电设备振动信号特征提取与模式识别

LabVIEW开发高压配电设备振动信号特征提取与模式识别 矿用高压配电设备是井下供电系统中的关键设备之一&#xff0c;肩负着井下供配电和供电安全的双重任务&#xff0c;其工作状态直接影响着井下供电系统的安全性和可靠性。机械故障占配电总故障的70%。因此&#xff0c;机械故…

报错Uncaught (in promise) Error: Manifest request to...

在使用nuxt框架时&#xff0c;出现如下报错&#xff1a; 解决方案&#xff1a; 不要打开两个以上的开发者工具更换nuxt的端口号 参考资料&#xff1a;https://github.com/nuxt/nuxt.js/issues/6202

DP(状态机模型)

状态机模型和01背包问题的区别就在于&#xff0c;01背包中每个物品选或不选都是独立的&#xff0c; 不受前者约束不对后者产生影响&#xff0c;而状态机不一样。换成01那种状态之间的转化图来看的话,01背包中0和1的转化不受任何约束&#xff0c;可以说是有向完全图&#xff1b;…

浅析 C 语言的共用体、枚举和位域

前言 最近在尝试阅读一些系统库的源码&#xff0c;但是其中存在很多让我感到既熟悉又陌生的语法。经过资料查阅&#xff0c;发现是 C 语言中的共用体和位域。于是&#xff0c;趁着课本还没有扔掉&#xff0c;将一些相关的知识点记录在本文。 文章目录 前言共用体 (union)枚举…

理解 Python 的 for 循环

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 在本篇博客中&#xff0c;我们将讨论 Python 中 for 循环的原理。 我们将从一组基本例子和它的语法开始&#xff0c;还将讨论与 for 循环关联的 else 代码块的用处。 然后我们将介绍迭代对象、迭代器和迭代器协议&…

Android 14重要更新预览

Android 14重要更新预览 国际化 Android 14 在 Android 13 的基础上进一步扩展了按应用设定语言功能&#xff0c;提供了一些额外的功能&#xff1a; 自动生成应用的 localeConfig&#xff1a;从 Android Studio Giraffe Canary 7 和 AGP 8.1.0-alpha07 开始&#xff0c;您可以…

Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis tbms

​ 功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查…