Qt之在运行时加载共享库

简介: 简述在 Windows 上,共享库由 .dll 表示;在 Linux 上,由 .so 表示。一个共享库中的符号被设计为导出的,以便客户端可以从中导入符号。

简述

在 Windows 上,共享库由 .dll 表示;在 Linux 上,由 .so 表示。一个共享库中的符号被设计为导出的,以便客户端可以从中导入符号。

要使用共享库,除了 Qt之创建并使用共享库 中介绍的方式之外,Qt 还提供了一种机制,可以在运行时加载共享库,通过 QLibrary 来实现。

版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820

认识 QLibrary

QLibrary 用于在运行时加载共享库,一个完整的加载流程大概分为以下几步:

  • 构造 QLibrary 实例
  • setFileName():指定共享库的文件名(也可以通过 QLibrary 的构造函数来设置)
  • load():动态加载共享库(isload() 检查加载是否成功)
  • resolve():解析共享库中的符号(如果库还没有加载,那么 resolve() 将隐式地尝试加载)
  • unload():卸载共享库

QLibrary 有一个很强大的特性 - 在运行时对共享库提供了平台独立的访问。对于库路径,QLibrary 在内部会做以下处理:

  • 如果文件名是绝对路径,则首先尝试加载该路径。若无法找到文件,则尝试使用不同平台的特定文件前缀(例如:Unix 和 Mac 上的 lib)和后缀(例如:Unix 上的 .so、Mac 上的 .dylib、或 Windows 中的 .dll)的名称。
  • 如果文件路径不是绝对的,那么 QLibrary 会修改搜索顺序,首先尝试系统特定的前缀和后缀,然后再指定文件路径。

这使得可以指定仅由其 basename(即:没有 .dll.so 后缀)标识的共享库,因此相同的代码可以在不同的操作系统上工作。尽管如此,但仍建议尽量减少查找库的次数。

注意: 一个共享库可以被 QLibrary 的多个实例访问,加载完成后,库将一直保存在内存中,直到应用程序终止。在使用 unload() 卸载库时,如果 QLibrary 的其他实例使用了相同的库,那么调用将失败,并且只有当每个实例都调用 unload() 时才会卸载。

使用 QLibrary 的优点

在运行时使用 QLibrary 加载共享库,有很多优点:

  • 无需使用 .h 头文件和 .lib 文件,就可以编译应用程序。
  • 只需将 dll 文件和可执行程序放在一起
  • 可以在没有 dll 的情况下启动可执行程序,因为 dll 将在运行时(按需)加载。
  • 有助于生成一个较小的可执行程序

创建共享库

Qt之创建并使用共享库 一样,在 Qt Creator 中创建两个项目:

  • SharedLib:是一个 C++ 共享库项目,其中有一个导出符号。
  • SharedLibClient:是一个 Qt 控制台应用程序,在运行时调用 SharedLib。

sharedlib_global.h 可以确保正确的宏能够被调用:

#ifndef SHAREDLIB_GLOBAL_H
#define SHAREDLIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(SHAREDLIB_LIBRARY)
#  define SHAREDLIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define SHAREDLIBSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // SHAREDLIB_GLOBAL_H

sharedlib.h 包含了导出的符号:

#ifndef SHAREDLIB_H
#define SHAREDLIB_H

#include "sharedlib_global.h"

extern "C" {
    SHAREDLIBSHARED_EXPORT int subtract(int x, int y);
}

#endif // SHAREDLIB_H

sharedlib.cpp 包含了具体的实现:

#include "sharedlib.h"

int subtract(int x, int y)
{
    return x - y;
}

注意: 对于要解析的函数名,必须将其导出为 C 函数。这意味着如果库是用 C++ 编译器编译的,那么函数必须被包装在一个 extern "C" 块中。

此外,还必须使用 Q_DECL_EXPORTQ_DECL_IMPORT 从库中显式导出该函数。

在运行时加载共享库

创建一个简单的客户端(SharedLibClient) - Qt Console Application,它将使用 SharedLib 库中的 subtract() 函数。效果如下:

这里写图片描述

在 main.cpp 文件中,使用 QLibrary 在运行时加载共享库:

#include <QCoreApplication>
#include <QLibrary>
#include <qDebug>

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

    // SharedLibd.dll 与可执行程序位于同一目录
    QLibrary lib("SharedLibd");

    // 加载共享库
    if (lib.load()) {
        typedef int (*Fun)(int, int);
        // 解析符号
        Fun sub = (Fun) lib.resolve("subtract");
        if (sub) {
            int result = sub(5, 2);
            qDebug() << result;
        } else {
            qDebug() << "Can not resolve subtract";
        }
        // 卸载共享库
        lib.unload();
    } else {
        qDebug() << lib.errorString();
    }
    return a.exec();
}

在 Debug 模式下运行项目,结果会显示在控制台输出上。

目录
相关文章
|
3月前
【Qt 学习笔记】使用QtCreator创建及运行项目 | 项目初始代码解释
【Qt 学习笔记】使用QtCreator创建及运行项目 | 项目初始代码解释
513 1
|
3月前
|
存储 C语言 Windows
音视频使用qt测试ffmpeg接口时无法运行
音视频使用qt测试ffmpeg接口时无法运行
83 0
|
9月前
|
存储 Cloud Native API
C++ QT监测可执行文件exe是否运行
C++ QT监测可执行文件exe是否运行
|
1月前
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
116 1
|
1月前
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
|
3月前
|
编译器
QT creator开发环境下 界面更改后运行程序不能实时更新或者在源文件添加该控件后无法编译的问题
在使用QT Creator开发界面的过程中,偶尔会出现添加控件后,运行程序后,界面控件无法更新的情况,或者在源文件使用该控件却出现无法编译的情况,使用QT Creator 4.8.2也会出现这个情况,也不知道这种情况会不会在以后有所改善。
122 0
|
3月前
|
SQL 安全 数据库连接
【Qt运行流程详解】从启动到事件循环的深入解读
【Qt运行流程详解】从启动到事件循环的深入解读
267 2
|
11月前
|
Ubuntu 编译器 网络安全
RK3568开发笔记(七):在宿主机ubuntu上搭建Qt交叉编译开发环境,编译一个Demo,目标板运行Demo测试
在之前的博文中已经搭建好了一个比较完善的ubuntu宿主机,都很完善了但是发现没有Qt交叉编译开发环境,所以还需要搭建一套Qt交叉编译开发环境。
如何解决Qt工程在其他电脑上无法运行的问题!(error: cannot open C:\Users???\AppData\Local\Temp\main.obj.5136.0.jom)
如何解决Qt工程在其他电脑上无法运行的问题!(error: cannot open C:\Users???\AppData\Local\Temp\main.obj.5136.0.jom)
|
编译器 C++ Windows
Qt程序运行依赖环境打包方法:windeployqt方法
3分钟学会Qt程序运行依赖环境打包方法:windeployqt方法!
400 0
Qt程序运行依赖环境打包方法:windeployqt方法