qt子目录项工程模板及动态库二进制兼容测试实现

概述

本篇文章是在qtcreator源码学习的支线知识,主线在这里1,主要目的是两个:

  1. 写一个qt subdir工程模板方便后续开发套用
  2. 测试动态库二进制兼容

设计思路

设计思路是写一个qApplication,调用两个库分别是LeeWidget和LeeLabel,LeeLabel是LeeWidget的子类,生成这两个动态库到指定目录。

由于LeeLabel是子类,理论上在不考虑二进制兼容时运行会出问题,通过d指针来实现兼容;

源代码解析

subdir子目录项结构如下图所示:

在这里插入图片描述

CONFIG += ordered的作用是按照顺序编译;

MainWindow

主工程的pro文件如下所示,突然发现LIBS好像有点重复不过没什么影响,对于CONFIG里几个参数说明查到一篇文章写得不错,附上链接Qt指定临时文件生成目录

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += debug_and_release warn_on plugin

TARGET = LeeMainWindow
TEMPLATE = app

CONFIG(debug, debug|release) {
    DESTDIR             =  ../../bin/Debug$$arch
    LIBS                += -L../../bin/Debug$$arch
    OBJECTS_DIR 	=  ../../bin/Debug$$arch/$${TARGET}/obj
    MOC_DIR      	=  ../../bin/Debug$$arch/$${TARGET}/moc
    RCC_DIR 		=  ../../bin/Debug$$arch/$${TARGET}/rcc
    UI_DIR 		=  ../../bin/Debug$$arch/$${TARGET}/ui
} else {
    DESTDIR             =  ../../bin/Release$$arch
    LIBS                += -L../../bin/Release$$arch
    OBJECTS_DIR 	=  ../../bin/Release$$arch/$${TARGET}/obj
    MOC_DIR       	=  ../../bin/Release$$arch/$${TARGET}/moc
    RCC_DIR 		=  ../../bin/Release$$arch/$${TARGET}/rcc
    UI_DIR 		=  ../../bin/Release$$arch/$${TARGET}/ui
}

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../LeeLabel/ -lLeeLabeld
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../LeeLabel/ -lLeeLabeld
else:unix: LIBS += -L$$OUT_PWD/../LeeLabel/ -lLeeLabeld

INCLUDEPATH += $$PWD/../LeeLabel
DEPENDPATH += $$PWD/../LeeLabel

win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../LeeWidget/release/ -lLeeWidgetd
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../LeeWidget/debug/ -lLeeWidgetd
else:unix: LIBS += -L$$OUT_PWD/../LeeWidget/ -lLeeWidgetd

INCLUDEPATH += $$PWD/../LeeWidget
DEPENDPATH += $$PWD/../LeeWidget

UI界面

如下图所示,做了一个加减法计算接口。

在这里插入图片描述

动态库函数调用

void MainWindow::slot_CalculateButtonClick()
{
    qreal result = 0;
    qreal a = 0, b = 0;
    a = ui->numA_LE->text().toDouble();
    b = ui->numB_LE->text().toDouble();
    if (ui->leeLabelPlus_RB->isChecked())
    {
        result = m_label->pluseTwo(a, b);
    }
    else if (ui->leeLabelMinus_RB->isChecked())
    {
        result = m_label->minusTwo(a, b);
    }
    else if (ui->leeWidgetPlus_RB->isChecked())
    {
        result = m_widget->pluseTwo(a, b);
    }
    ui->result_Label->setText(QString::number(result,'f', 2));
}

这一段就是核心代码了,调用动态库中的函数。

class LeeWidget

这是我使用d指针实现的一个类,该类是QObject的子类,pro文件如下所示:

QT += core


TEMPLATE = lib
DEFINES += LEEWIDGET_LIBRARY

CONFIG += c++11

TARGET = $$qtLibraryTarget($$TARGET)
#TARGET = LeeWidget

CONFIG(debug, debug|release) {
    DESTDIR             = ../../bin/Debug$$arch
    LIBS                += -L../../bin/Debug$$arch
    OBJECTS_DIR 	=  ../../bin/Debug$$arch/$${TARGET}/obj
    MOC_DIR      	=  ../../bin/Debug$$arch/$${TARGET}/moc
    RCC_DIR 		=  ../../bin/Debug$$arch/$${TARGET}/rcc
} else {
    DESTDIR             =  ../../bin/Release$$arch
    LIBS                += -L../../bin/Release$$arch
    OBJECTS_DIR 	=  ../../bin/Release$$arch/$${TARGET}/obj
    MOC_DIR       	=  ../../bin/Release$$arch/$${TARGET}/moc
    RCC_DIR 		=  ../../bin/Release$$arch/$${TARGET}/rcc
}

SOURCES += \
    leewidget.cpp

HEADERS += \
    LeeWidget_global.h \
    global.h \
    leewidget.h \
    leewidget_p.h

该类主要提供加法的接口,但加法函数的实际实现通过调用d指针指向的私有类对象函数实现。

显式类

/****************************************************************
 Doc    :   leewidget.h
 Author :   BingLee
 Date   :   2020-12-07
 Info   :   .
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/

#ifndef LEEWIDGET_H
#define LEEWIDGET_H

#include "LeeWidget_global.h"
#include <QObject>

class LeeWidgetPrivate;

class LEEWIDGET_EXPORT LeeWidget : public QObject
{
    Q_OBJECT
public:
    LeeWidget(QObject *parent = 0);
    virtual ~LeeWidget();

    qreal pluseTwo(qreal firstNum, qreal secondNum);

protected:
    /*
       该接口的主要作用是避免每有一个继承子类,就会为相应的LeeWidgetPrivate分配空间。
       https://blog.csdn.net/Bing_Lee
    */
    LeeWidget(LeeWidgetPrivate &d_ptr);
    LeeWidgetPrivate *d;
};

#endif // LEEWIDGET_H

隐式类

/****************************************************************
 Doc    :   LeeWidget_p.h
 Author :   BingLee
 Date   :   2020-12-07
 Info   :   .
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#ifndef LEEWIDGET_P_H
#define LEEWIDGET_P_H

#include "leewidget.h"

 class LeeWidgetPrivate
 {
 public:
     LeeWidgetPrivate(LeeWidget *q_ptr)
         : q(q_ptr)
     {}
     //这里是实际实现加法功能的函数。
     qreal plusAandB(qreal a, qreal b);

 protected:
     LeeWidget *q;
 };

#endif // LEEWIDGET_P_H

函数实现

#include "leewidget.h"
#include "LeeWidget_p.h"


LeeWidget::LeeWidget(QObject *parent)
    : QObject(parent),
      d(new LeeWidgetPrivate(this))
{
}

LeeWidget::~LeeWidget()
{
    delete d;
}

qreal LeeWidget::pluseTwo(qreal firstNum, qreal secondNum)
{
    return d->plusAandB(firstNum, secondNum);
}

LeeWidget::LeeWidget(LeeWidgetPrivate &d_ptr)
    : d(&d_ptr)
{

}

qreal LeeWidgetPrivate::plusAandB(qreal a, qreal b)
{
    return a+b;
}

class LeeLabel

显式类

/****************************************************************
 Doc    :   leelabel.h
 Author :   BingLee
 Date   :   2020-12-07
 Info   :   .
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#ifndef LEELABEL_H
#define LEELABEL_H

#include "LeeLabel_global.h"
#include "leewidget.h"

class LeeLabelPrivate;

class LEELABEL_EXPORT LeeLabel : public LeeWidget
{
    Q_OBJECT
public:
    LeeLabel();

    qreal minusTwo(qreal firstNum, qreal secondNum);

protected:
    LeeLabel(LeeLabelPrivate &d_ptr);
};

#endif // LEELABEL_H

隐式类

/****************************************************************
 Doc    :   leelabel_p.h
 Author :   BingLee
 Date   :   2020-12-07
 Info   :   .
 https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#ifndef LEELABEL_P_H
#define LEELABEL_P_H

#include "leelabel.h"
#include "LeeWidget_p.h"

class LeeLabelPrivate : public LeeWidgetPrivate
{
public:
    LeeLabelPrivate()
        : LeeWidgetPrivate(0)
    {}
    //这里是实际实现减法功能的函数。
    qreal minusAandB(qreal a, qreal b);
    QString m_name;
};

#endif // LEELABEL_P_H

结果

编译目录如下所示:

在这里插入图片描述

实现结果如下图所示:

在这里插入图片描述

二进制兼容测试初步试验没有出现兼容问题,后期用vs编译测试下。

如果喜欢本文,请帮忙给博主点赞、评论、关注三连哦~

源代码下载链接


  1. 我勒个去,竟然还没发那篇… TODO_后边写了替换下 ↩︎

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐