12-4_Qt 5.9 C++开发指南_创建和使用共享库

这篇具有很好参考价值的文章主要介绍了12-4_Qt 5.9 C++开发指南_创建和使用共享库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 创建共享库

除了静态库,Qt 还可以创建共享库,也就是 Windows 平台上的动态链接库。动态链接库项目编译后生成 DLL 文件,DLL 文件在 windows 平台上应用广泛。DLL 文件是在应用程序运行时加载的,不像静态库那样在编译期间就连编到应用程序里。若更新了 DLL 文件版本,只要接口未变,应用程序依然可以调用。

创建共享库项目,单击Qt Creator 的“File”->“New File or Project”菜单项,在 New File orProject 对话框中选择 Projects 组里的 Library,在右侧的具体类别中再选择 C++ Library,单击“Choose*·.”按钮后出现如下图 所示的向导对话框。

12-4_Qt 5.9 C++开发指南_创建和使用共享库,# Qt 5.9 C++开发指南,qt,c++,开发语言

在此对话框的 Type 下拉列表框里选择 Shared Library,并给项目命名,例如 mySharedLib,再选择项目保存目录。单击“Next”按钮后选择编译器,下一步选择需要包含的 Qt 模块,再下一步是类定义页面,在其中输入类的名称,这里仍然输入类名称为QWDialogPen,再下一步结束即可。

由向导生成的 mySharedLib项目包含文件 mySharedLib.pro、qwdialogpen.h 和qwdialogpen.cpp。此外还有一个特殊的头文件 mysharedlib_global.h。结构如下图所示:

12-4_Qt 5.9 C++开发指南_创建和使用共享库,# Qt 5.9 C++开发指南,qt,c++,开发语言
mysharedlib_global.h文件的内容如下:

#ifndef MYSHAREDLIB_GLOBAL_H
#define MYSHAREDLIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(MYSHAREDLIB_LIBRARY)
#  define MYSHAREDLIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define MYSHAREDLIBSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // MYSHAREDLIB_GLOBAL_H

这里定义了符号MYSHAREDLIBSHARED_EXPORT用于替代Qt的宏Q_DECL_EXPORT或Q_DECL_IMPORT。

一个共享库导出给用户使用的类、符号、函数等都需要用宏Q_DECL_EXPORT来定义导出,一个使用共享库的应用程序需要通过Q_DECL_IMPORT导入共享库里的可用对象。

在mySharedLib.pro文件中增加了符号MYSHAREDLIB_LIBRARY的定义,下面是mySharedLib.pro文件的主要内容:

QT       += widgets

TARGET = mySharedLib
TEMPLATE = lib

DEFINES += MYSHAREDLIB_LIBRARY
DEFINES += QT_DEPRECATED_WARNINGS

自动生成的 qwdialogpen.h 文件里的内容是对 QWDialogPen 类的定义,在类名称前使用MYSHAREDLIBSHARED_EXPORT,定义QWDialogPen 为一个导出的类。

#ifndef QWDIALOGPEN_H
#define QWDIALOGPEN_H

#include    <QDialog>
#include    <QPen>
#include    "mysharedlib_global.h"


namespace Ui {
class QWDialogPen;
}

class MYSHAREDLIBSHARED_EXPORT QWDialogPen : public QDialog
{ //QPen属性设置对话框
    Q_OBJECT
private:
    QPen    m_pen; //成员变量
public:
    explicit QWDialogPen(QWidget *parent = 0);
    ~QWDialogPen();

    void    setPen(QPen pen); //设置QPen,用于对话框的界面显示
    QPen    getPen(); //获取对话框设置的QPen的属性
    static  QPen    getPen(QPen  iniPen, bool &ok);  //静态函数

private slots:
    void on_btnColor_clicked();
private:
    Ui::QWDialogPen *ui;
};

#endif // QWDIALOGPEN_H

将 12.3 节静态库项目里的文件 qwdialogpen.h、qwdialogpen.cpp 和 qwdialogpen.ui 复制到本项目目录下,覆盖自动生成的初始文件,但是修改文件 qwdialogpen.h 里的类的定义,在类名称前增加MYSHAREDLIBSHARED_EXPORT 宏,并加入mysharedlib global.h 的包含语句。

项目的文件准备好之后就可以编译生成 DLL 文件,根据使用的编译器不同,生成的文件有些区别。

  • 若使用 MSVC 编译,编译后会生成 mySharedLib.dllmySharedLib.lib 两个文件,mySharedLib.dll 在运行应用程序时调用,mySharedLib.lib 在应用程序隐式调用动态链接库时使用
  • 若使用 MinGW 编译,编译后会生成 mySharedLib.dll 和 libmySharedLib.a 两个文件,mySharedLib.dll 在运行应用程序时调用,libmySharedLib.a 在应用程序隐式调用动态链接库时使用。

采用 debug 和release 不同模式生成的文件只能当应用程序在 debug 或release 模式下编译或调用。

由于动态库的代码和上篇静态库的基本一样,只是多了mysharedlib global.h文件,这里就不再赘述了。

2. 使用共享库

2.1 共享库的调用方式

调用动态链接库有两种形式,隐式链接 (implicit linking)调用和显式链接 (explicit linking)调用。

  • 隐式链接调用是在编译应用程序时,有动态库的 lib 文件(或a 文件)和 h 头文件,知道 DLL中有哪些接口类和函数,编译时就隐式地生成必要的链接信息,使用 DLL 中的类或函数时根据h头文件中的定义使用即可。应用程序运行时将自动加载 DLL 文件。隐式链接调用主要用于同一种编程软件(如 Qt)生成的代码的共享。—— 使用 lib 文件+DLL 文件

  • 显式链接调用是只有 DLL 文件,知道 DLL 里的函数原型,使用 QLibrary 类对象在应用程序里动态加载 DLL 文件,声明函数原型,并使用 DLL 里的函数。这种方式需要在应用程序里声明函数原型,并解析 DLL 里的函数。

2.2 隐式链接调用共享库:使用 .h、lib 文件+DLL 文件

创建一个基于QMainWindow 的应用程序 shareLibUser,程序功能与 12.3 节的 LibUser 项目一样,将LibUser 项目的 mainwindow 相关3 个文件mainwindow.h、mainwindow.cpp 和mainwindow.ui复制到 shareLibUser 项目下,替换自动生成的文件。

在 shareLibUser 项目文件目录下新建一个 include 目录,将 mySharedLib 项目的两个头文件qwdialogpen.h mysharedlib_global.h 复制到此目录下。若使用 MSVC 编译器,则将 release 版本的mySharedLib.lib 复制到此目录下,debug 版本的 mySharedLib.lib 更名为 mySharedLibd.lib 复制到此目录下;若使用 MinGW 编译器,则复制 release 版本的 libmySharedLib.a,debug 版本的libmySharedLib.a 更名为 libmySharedLibd.a 复制到此目录下。

为应用程序增加动态链接库,右键单击 shareLibUser 项目节点,在快捷菜单里单击“Add Library···”菜单项,在出现的向导对话框里首先选择添加的库类型为“Extermal Library”,在向导第二步设置导入的动态库文件(见下图)。

12-4_Qt 5.9 C++开发指南_创建和使用共享库,# Qt 5.9 C++开发指南,qt,c++,开发语言
在上图中,选择项目 include 目录下的 mySharedLib.lib 文件或libmySharedLib.a 作为库文其他设置如上图所示。

完成后在shareLibUser.pro 文件中自动增加项目设置的语句如下:(目的也是为了下面的程序,也可以不通过UI操作,自己写相应的代码)

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/include/ -lmySharedLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/include/ -lmySharedLibd

INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

项目编译时,会根据当前是 release 还是 debug 模式,自动添加相应的库文件。这里添加库文件只是使用了动态库的导出定义,而不是将库的实现代码连接到应用程序的可执行文件里。主窗体类 MainWindow 的功能与上篇静态库 的程序完全一致,调用共享库里的类QWDialogPen也无需特别说明,只需包含头文件 qwdialogpen.h 即可。

注意:必须将动态链接库文件 mySharedLib.dll复制到可执行文件的目录下,程序才可以正常运行mySharedLib.dll 的 debug 和 release 版本必须分别用于应用程序的 debug 和 relcase 版本,否则运行时出错。

使用动态链接库可以很方便地扩展应用程序的功能,但是 DLL 文件需要随应用程序一起发布,并且编译 DLL和应用程序的 Qt 版本最好保持一致,否则需要考虑二进制兼容问题。关于二进制兼容可以参考:Qt源代码中二进制兼容及d、q指针的理解

2.2.1 shareLibUser.pro

#-------------------------------------------------
#
# Project created by QtCreator 2017-04-05T16:30:52
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = shareLibUser
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/include/ -lmySharedLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/include/ -lmySharedLibd

INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

2.2.2 mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include    <QPen>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QPen    mPen;

protected:
    void    paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private slots:
//    void on_pushButton_clicked();

    void on_action_Pen_triggered();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

2.2.3 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include    "qwdialogpen.h"
#include    <QPainter>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent *event)
{//绘图
    Q_UNUSED(event);

    QPainter    painter(this);
    QRect rect(0,0,width(),height()); //viewport矩形区
    painter.setViewport(rect);//设置Viewport
    painter.setWindow(0,0,100,50); // 设置窗口大小,逻辑坐标
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::TextAntialiasing);

    painter.setPen(mPen);
    painter.drawRect(10,10,80,30);
}

void MainWindow::on_action_Pen_triggered()
{//设置Pen
    bool    ok=false;
    QPen    pen;
    pen=QWDialogPen::getPen(mPen,ok);
    if (ok)
    {
        mPen=pen;
        this->repaint();
    }
}

2.3 显式链接调用共享库:使用 .h和DLL 文件

显式链接调用共享库是在应用程序运行时才加载共享库文件,并调用库里的函数的。应用程序编译时无需共享库的任何文件,只需知道函数名和函数的原型即可。所以,这种方式可以调用其他语言编写的 DLL 文件,例如用 Delphi 生成的一个DLL 文件。

显式链接调用共享库是通过 QLibrary 类实现的。QLibrary 是与平台无关的,用于在运行时载入共享库,一个 QLibrary 对象只对一个共享库进行操作。

一般在 QLibrary 的构造函数中传递一个文件名,可以是带路径的绝对文件名,也可以是不带后缀的单独文件名。QLibrary 会根据运行的平台自动查找不同后缀的共享库文件,例如 Unix 上是.so”,Mac上是“.dylib”,Windows 上是“.dll”。

作为示例,用 Delphi编写一个 DLL 项目,生成一个 DelphiDLL.dll文件,这个文件里只有一个函数,函数的原型为:

function triple(N;integer):integer;

它会计算传递参数N的3倍值并返回。

在Qt Creator 里创建一个基于 QMainWindow 的应用程序DelphiDLLUser,设计一个简单的界面,运行时下图所示。单击按钮时将根据输入,调用动态链接库 DelphiDLL.d11里的triple()函数,计算结果并显示在输出编辑框里。

按钮的槽函数代码如下:

void MainWindow::on_pushButton_clicked()
{
    QLibrary myLib("DelphiDLL");

    if (myLib.isLoaded())
        QMessageBox::information(this,"信息","DelphiDLL.DLL已经被载入,第1处");
    typedef int (*FunDef)(int); //函数原定定义
    FunDef myTriple = (FunDef) myLib.resolve("triple"); //解析DLL中的函数
    int V=myTriple(ui->spinInput->value()); //调用函数
    ui->spinOutput->setValue(V);
    if (myLib.isLoaded())
        QMessageBox::information(this,"信息","DelphiDLL.DLL已经被载入,第2处");
}

在定义QLibrary对象实例 myLib 时传递了共享库文件名“DelphiDLL”,这里不需要给出后缀名。DelphiDLL.dll 文件必须在应用程序同一目录、系统目录或可搜索目录下。

QLibrary 有几个函数用于 DLL文件的载入与卸载:

  • load()用于手动载入 DLL 文件到内存里,一般无需手工调用此函数,在DLL里的函数第一次被使用时 QLibrary 会自动调用此函数;

  • isLoaded()用于判断 DLL是否已经被载入内存;

  • unload()用于将DLL从内存中卸载。

一个动态链接库在内存里只能有一个实例,也就是即使有多处调用了这个动态链接库里的函数,它也只会被载入一次,如果不是所有的实例都使用 unload()卸载它,那么它会在应用程序退出时才卸载。

在槽函数on_pushButton_clicked()的代码里,有两处QMessageBox 显示信息。在运行应用程序,第一次单击按钮时,只有第 2 处信息框显示,说明声明了 QLibrary 对象后,动态链接库没有立即被载入内存;第二次单击按钮时,两处信息框会先后显示,说明动态链接库上次载入内存后还在内存里。

显式调用动态链接库里的函数,需要声明函数原型的类型,即:

typedef int (*FunDef)(int); //函数原定定义

然后使用QLibrary的resolve()函数解析需要调用的函数。

FunDef myTriple = (FunDef) myLib.resolve("triple"); //解析DLL中的函数

这样就定义了一个函数 myTriple,用于实现 DLL文件里的函数"triple"的功能,当然重新声明的函数名称可以和 DLL 里的函数名称完全相同。

如果 DelphiDLL.dll 文件没有复制到应用程序目录下,则编译和启动应用程序都不会出错,只有单击按钮调用 DLL 里的函数时才会出错。所以,要使应用程序正常运行,需要将 DelphiDLL.dIl文件复制到应用程序目录下。(实际操作时发现即使复制进去,点击后会显示“程序异常结束”,后期实践时再测试)
12-4_Qt 5.9 C++开发指南_创建和使用共享库,# Qt 5.9 C++开发指南,qt,c++,开发语言文章来源地址https://www.toymoban.com/news/detail-621619.html

到了这里,关于12-4_Qt 5.9 C++开发指南_创建和使用共享库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据)

    11-2_Qt 5.9 C++开发指南_QSqlQueryModel的使用(QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据)

    从下图中可以看到,QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel封装了执行 SELECT 语句从数据库查询数据的功能,但是 QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据。 QSqlQueryModel 类的主要接口函数见表 11-10(省略了函数中的 const 和缺省参数)。 使用QSqlQueryM

    2024年02月15日
    浏览(10)
  • 09-1_Qt 5.9 C++开发指南_Qchart概述

    09-1_Qt 5.9 C++开发指南_Qchart概述

    Qt Charts 可以很方便地绘制常见的折线图、柱状图、饼图等图表,不用自己耗费时间和精力开发绘图组件或使用第三方组件了。 本章首先介绍 Qt Charts 的基本特点和功能,以画折线图为例详细说明 Qt Charts 各主要部件的操作方法,再介绍各种常用图表的绘图方法,最后介绍鼠标

    2024年02月13日
    浏览(18)
  • 07-3_Qt 5.9 C++开发指南_文件目录操作

    07-3_Qt 5.9 C++开发指南_文件目录操作

    Qt 为文件和目录操作提供了一些类,利用这些类可以方便地实现一些操作。Qt 提供的与文件和目录操作相关的类包括以下几个。 QCoreApplication:用于提取应用程序路径、程序名等文件信息 QFile: 除了打开文件操作外,QFile 还有复制文件、删除文件等功能 QFileInfo:用于提取文件的信

    2024年02月13日
    浏览(39)
  • 16-1_Qt 5.9 C++开发指南_多语言界面

    16-1_Qt 5.9 C++开发指南_多语言界面

    有些软件需要开发多语言界面版本,如中文版和英文版,并且在软件里可以方便地切换界面语言。Qt 为多语言界面提供了很好的支持,使用 Qt 的一些规则和工具,可以很方便地为应用程序开发提供多语言界面支持。 用 Qt 开发多语言界面应用程序,主要包括以下几个步骤。

    2024年02月14日
    浏览(14)
  • 12-2_Qt 5.9 C++开发指南_自定义Qt Designer 插件(UI 设计器自定义界面组件的 Widget 插件,直接安装到 UI设计器组件面板里,如同 Qt 自带的界面设计组件一样)

    12-2_Qt 5.9 C++开发指南_自定义Qt Designer 插件(UI 设计器自定义界面组件的 Widget 插件,直接安装到 UI设计器组件面板里,如同 Qt 自带的界面设计组件一样)

    上篇使用提升法(promotion)来创建自定义组件,本篇为 UI 设计器设计自定义界面组件的 Widget 插件,直接安装到 UI设计器的组件面板里,如同 Qt 自带的界面设计组件一样使用,在设计时就能看到组件的实际显示效果,只是编译和运行时需要使用到插件的动态链接库 (Windows 平台上

    2024年02月05日
    浏览(29)
  • 07-1_Qt 5.9 C++开发指南_文件系统及文件读写_文本文件读写(使用 QTextStream 进行文件读写更为方便)

    07-1_Qt 5.9 C++开发指南_文件系统及文件读写_文本文件读写(使用 QTextStream 进行文件读写更为方便)

    文本文件是指以纯文本格式存储的文件,例如用 Qt Creator 编写的 C++程序的头文件 (.h 文件)和源程序文件 (.cpp 文件)。HTML 和 XML 文件也是纯文本文件,只是其读取之后需要对内容进行解析之后再显示。 Qt 提供了两种读写纯文本文件的基本方法, 一种是用 QFile 类的 IODevice 读写

    2024年02月13日
    浏览(7)
  • 16-3_Qt 5.9 C++开发指南_使用QStyle 设置界面外观_实现不同系统下的界面效果的匹配

    16-3_Qt 5.9 C++开发指南_使用QStyle 设置界面外观_实现不同系统下的界面效果的匹配

    Qt 是一个跨平台的类库,相同的界面组件在不同的操作系统上显示效果是不一样的。QStyle是封装了 GUI 界面组件外观的抽象类,Qt 定义了 QStyle 类的一些子类,应用于不同的操作系统如QWindowsStyle和QMacStyle 等。这些样式是 QtGUI 模块自带的,在不同的平台上编译运行的程序具有缺

    2024年02月13日
    浏览(15)
  • 15-1_Qt 5.9 C++开发指南_Qt多媒体模块概述

    15-1_Qt 5.9 C++开发指南_Qt多媒体模块概述

    多媒体功能指的主要是计算机的音频和视频的输入、输出、显示和播放等功能,Qt 的多媒体模块为音频和视频播放、录音、摄像头拍照和录像等提供支持,甚至还提供数字收音机的支持。本章将介绍 Qt 多媒体模块的功能和使用。 Qt 多媒体模块提供了很多类,可以实现如下的

    2024年02月13日
    浏览(15)
  • 16-4_Qt 5.9 C++开发指南_Qt 应用程序的发布

    用 Qt 开发一个应用程序后,将应用程序提供给用户在其他计算机上使用就是应用程序的发布。应用程序发布一般会提供一个安装程序,将应用程序的可执行文件及需要的运行库安装到用户计算机上,即使用户计算机上没有安装 Qt 也能正常运行安装的程序。 Qt的应用程序发布

    2024年02月14日
    浏览(45)
  • 04-5_Qt 5.9 C++开发指南_QComboBox和QPlainTextEdit

    04-5_Qt 5.9 C++开发指南_QComboBox和QPlainTextEdit

    QComboBox 是下拉列表框组件类,它提供一个下拉列表供用户选择,也可以直接当作一个QLineEdit 用作输入。OComboBox 除了显示可见下拉列表外,每个项 (item,或称列表项)还可以关联一个 QVariant 类型的变量,用于存储一些不可见数据。 QPlainTextEdit 是一个多行文本编辑器,用于显示

    2024年02月14日
    浏览(14)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包