Qt之创建并使用共享库

http://blog.csdn.net/liang19890820/article/details/77337088

简述

在 Windows 中,有动态链接库(DLL - Dynamic Link Library);在 Linux 中,有共享库(Shared Library),它们是相同的!

由于平台和编译器的差异,输出的库文件也不同:

  • 在 Windows 中,MinGW 将输出 .a.dll;MSVC 将输出 .lib.dll
  • 在 Linux 中,MinGW 将输出 .so.so.1.so.1.0.so.1.0.0 - .lib

.a.so 是导入库,它们有助于将我们的代码链接到库中,并且在构建文件时需要。

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

创建共享库

要创建一个共享库,需要执行以下几个步骤:

  • 文件 -> 新建文件或项目,选择:Library -> C++ 库:

这里写图片描述

  • 选择“共享库”,然后输入“名称”(这里以 SharedLib 为例),并选择“创建路径”:

注意: “类型”下拉列表中有三个选项,分别是:共享库、静态链接库、Qt Plugin(Qt 插件)。

这里写图片描述

  • 选择一个适当的“构建套件”
  • 选择需要的模块(默认勾选“QtCore”,如果需要其他模块,请自行勾选。例如:界面需要依赖 QtWidgets)。
  • 执行要创建的源码文件的基本信息(默认即可)
  • 完成向导

项目文件

在项目创建完成之后,Qt Creator 会帮我们生成一系列相关文件,目录结构如下:

这里写图片描述

查看 .pro,并对其稍作修改:

TARGET = SharedLib

# 新增部分
CONFIG += debug_and_release
CONFIG(debug, debug|release) {
    unix: TARGET = $$join(TARGET,,,_debug)
    else: TARGET = $$join(TARGET,,,d)
}

TEMPLATE = lib
DEFINES += SHAREDLIB_LIBRARY
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • TARGET:指定库的名称
  • TEMPLATE:模板的意思,将其指定为 lib,是要告诉 qmake 我们需要生成的是一个库文件(app 为可执行程序)。
  • DEFINES:用于定义编译选项
  • CONFIG(新增部分):用于编译控制,区分 DebugRelease 版本的库名称(DebugdRelease 不带)。

这里,同时出现了一个非常重要的文件 - {projectName}_global.h,这是 Qt Creator 帮我们创建的,内容如下:

#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
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

为什么要自动创建这么一个文件呢?为了明确这一点,先来了解一些基本概念:

符号 - 函数、变量或类 - 包含在供客户端(例如:应用程序或其他库)使用的共享库中,必须以一种特殊的方式标记。这些符号被称为公共符号,它们被导出或公开可见。

在编译共享库时,必须将其标记为导出。为了在客户端使用共享库,一些平台可能需要一个特殊的导入声明。

为此,Qt 提供了两个特殊的宏:

  • Q_DECL_EXPORT:当编译共享库时,必须将其添加到使用的符号声明。
  • Q_DECL_IMPORT:当编译一个(使用了该共享库)客户端时,必须将其添加到使用的符号声明。

所以,要确保正确的宏能够被调用(无论是编译共享库本身,还是在客户端使用共享库),通常通过添加一个特殊的头文件({projectName}_global.h)来解决,这就是 sharedlib_global.h 存在的原因。

生成共享库

可以看到,生成的库中只有一个简单的类定义。为了便于使用,为其添加一些简单的函数:

sharedlib.h 内容如下:

#ifndef SHAREDLIB_H
#define SHAREDLIB_H

#include "sharedlib_global.h"

SHAREDLIBSHARED_EXPORT int subtract(int x, int y);

class SHAREDLIBSHARED_EXPORT SharedLib
{
public:
    SharedLib();
    int add(int x, int y);
};

#endif // SHAREDLIB_H
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

sharedlib.cpp 内容如下:

#include "sharedlib.h"

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

SharedLib::SharedLib()
{
}

int SharedLib::add(int x, int y)
{
    return x + y;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

构建(不运行)项目,会生成相应的 .lib.dll 文件。

注意: Debug 版本(带 d)为 SharedLibd.libSharedLibd.dllRelease 版本(不带 d)为 SharedLib.libSharedLib.dll

将应用程序与共享库链接

为了使用共享库,创建一个简单的客户端 - Qt Console Application,然后调用库中导出的符号,效果如下:

这里写图片描述

项目创建成功后,将刚才生成的共享库组织成以下结构:

  • SharedLibClient/
    • SharedLibClient.pro
    • main.cpp
    • 3rdparty/
      • SharedLib/
        • include/
          • sharedlib_global.h
          • sharedlib.h
        • lib/
          • SharedLibd.lib
          • SharedLib.lib

一切准备就绪,到了最关键的时刻 - 添加和使用库:

  • 右键项目 -> 添加库:

这里写图片描述

  • 选择链接到的库类型,这里选“外部库”:

这里写图片描述

  • 指定链接库和包含目录、平台等选项:

这里写图片描述

这时,.pro 中会自动添加以下代码:

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/3rdparty/SharedLib/lib/ -lSharedLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/3rdparty/SharedLib/lib/ -lSharedLibd

INCLUDEPATH += $$PWD/3rdparty/SharedLib/include
DEPENDPATH += $$PWD/3rdparty/SharedLib/include
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • $$PWD 用于指定包含 .pro 文件的目录的完整路径
  • INCLUDEPATH - 指定编译项目时应该被搜索的 #include 目录
  • LIBS - 指定链接到项目中的库列表

开始测试,main.cpp 内容如下:

#include <QCoreApplication>
#include <qDebug>
#include "sharedlib.h"

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

    // 测试库
    SharedLib lib;
    qDebug() << lib.add(2, 3);

    qDebug() << subtract(5, 2);

    return a.exec();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

OK,运行程序,效果如上所示。

注意: 在运行程序时,需要将对应的 dllDebug SharedLibd.dllReleaseSharedLib.dll) 拷贝到和可执行程序同一级目录下,否则会出错。

更多参考

版权声明:进步始于交流,收获源于分享!纯正开源之美,有趣、好玩、靠谱。。。作者:一去丶二三里 博客地址:http://blog.csdn.net/liang19890820

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,可以使用QLibrary类加载共享(.so文件)。QLibrary类提供了一个方便的接口来加载和使用共享。 以下是一个示例,演示如何使用QLibrary加载共享: ```cpp #include <QLibrary> #include <QDebug> int main() { // 加载共享 QLibrary myLib("myLibrary.so"); // 检查共享是否已成功加载 if (!myLib.load()) { qWarning() << "Could not load library:" << myLib.errorString(); return 1; } // 获取并调用中的函数 typedef int (*sumFunc)(int, int); sumFunc mySumFunc = (sumFunc)myLib.resolve("sum"); if (mySumFunc) { int result = mySumFunc(1, 2); qDebug() << "Result:" << result; } else { qWarning() << "Could not resolve function"; return 1; } // 卸载共享 myLib.unload(); return 0; } ``` 在这个例子中,我们首先创建一个QLibrary对象并指定要加载的共享的名称。然后,我们调用load()方法来实际加载共享。如果加载失败,我们打印出错误消息并退出程序。 接下来,我们使用resolve()方法获取共享中的函数,并将其转换为适当的函数指针类型。如果函数成功解析,我们可以使用函数指针来调用该函数。在这个例子中,我们将两个整数作为参数传递给sum()函数,并打印出结果。 最后,我们使用unload()方法卸载共享。 需要注意的是,使用QLibrary加载共享需要确保该已经编译为可共享的目标文件,并且已经安装在系统路径或指定的路径中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值