Evgenii Legotckoi
Evgenii LegotckoiҚаз. 9, 2018, 3:16 Т.Қ.

Qt/C++ - Сабақ 083. Динамикалық кітапхананы құру және оны басқа жобамен байланыстыру

Форумда динамикалық кітапхананы қалай құру және оны үшінші тарап жобасына дұрыс қосу туралы сұрақ туындады. Мерзімді түрде осындай сұрақтар туындайды, сондықтан бір нұсқаны қарастырайық - Qt Creator стандартты шеберлерінің көмегімен Windows үшін динамикалық кітапхана dll жасау.

Бұл жағдайда жоба кітапханалар ретінде құрастырылған, содан кейін негізгі жобаға қосылған қосалқы жобаларға бөлінген кезде опция қарастырылмайды. Өйткені бұл жобаның динамикалық ішкі кітапханалары болады. Теориялық тұрғыдан екілік файлдар түрінде таралатын сыртқы кітапхананы құрайық.

Екі жобаны жасайық:

  1. QuiLib - бұл бір диалогтық терезеден тұратын сыртқы динамикалық кітапхана болады. Бұл диалогтық терезе негізгі жобада ашылады.
  2. WithDynamicLibrary - осы динамикалық кітапхананы қосу үшін ғана пайдаланылатын жоба.

1-қадам

Qt Creator мәзірінде жобаны құруды таңдап, жобамыздың түрін таңдайық. Бұл C++ кітапханасы болады.

2-қадам

Жобаның атын және оның орналасқан жерін жазайық

3-қадам

Жобаны құруға арналған жинақтарды таңдайық.

Бұл жерде өте маңызды мәселе бар және оны жаңадан бастағандар ұмыта алады. Егер сіз белгілі бір нұсқаның компиляторын пайдаланып жобаны құрып жатсаңыз, онда бұл кітапханаларды тек сол нұсқаның компиляторы құрастыратын жобада ғана пайдалануға болады.

Мен бұл кітапхананы MSVC2017. компиляторымен құрастырамын

4-қадам

Қажетті модульдерді таңдаңыз. Біздің кітапхана үшін негізгі функционалдылық жеткілікті.

5-қадам

Онда қолданылатын кітапхана сыныбына ат берейік. Бұл жағдайда атау кітапхананың атымен бірдей болады. Бірақ сіз өзгерте аласыз. Бұл маңызды емес.

6-қадам

Сіз нұсқаны басқару жүйесін пайдаланасыз ба? Сондықтан жобаны нұсқаны басқару астында қосыңыз. Олай болмаса, ештеңе жасамаңыз. Кітапхананың құрылысын аяқтаңыз.

7-қадам

Жоба файлдарын қарастырайық және оларды аздап өзгертейік.

Жоба құрылымы

QuiLib.pro

Бұл файлда бұл кітапхана екендігі туралы ақпарат бар. Міне, осы жолда.

TEMPLATE = lib

Мұнда толық pro файл коды берілген

#-------------------------------------------------
#
# Project created by QtCreator 2018-10-09T19:33:33
#
#-------------------------------------------------

QT       += widgets

TARGET = QuiLib
TEMPLATE = lib

DEFINES += QUILIB_LIBRARY

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has 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 += \
        QuiLib.cpp

HEADERS += \
        QuiLib.h \
        quilib_global.h 

unix {
    target.path = /usr/lib
    INSTALLS += target
}

quilib_global.h

Экспортты анықтауға арналған тақырып кітапханада анықталады. Экспорттық анықтамамен белгіленетін сыныптар кітапханадан тыс пайдалануға қолжетімді болады.

#ifndef QUILIB_GLOBAL_H
#define QUILIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(QUILIB_LIBRARY)
#  define QUILIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define QUILIBSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // QUILIB_GLOBAL_H

QuiLib.h

Диалогтық терезенің тақырып файлын сәл түзетейік, өйткені бізге диалог қажет, яғни бұл тақырып файлындағы класс QDialog-тен мұралануы керек болады.

#ifndef QUILIB_H
#define QUILIB_H

#include "quilib_global.h"

#include <QDialog>

class QUILIBSHARED_EXPORT QuiLib : public QDialog
{

public:
    explicit QuiLib(QWidget* parent = nullptr);
};

#endif // QUILIB_H

QuiLib.cpp

Сондай-ақ біз QLabel көмегімен бұл сыртқы кітапхананың диалогтық терезесі екенін айту үшін диалогтық терезе конструкторының орындалуын жазамыз.

#include "QuiLib.h"

#include <QLabel>
#include <QGridLayout>


QuiLib::QuiLib(QWidget* parent) : QDialog(parent)
{
    QGridLayout* gridLayout = new QGridLayout(this);
    setLayout(gridLayout);
    gridLayout->addWidget(new QLabel("Hello world from dynamic library", this));
}

8-қадам

Жобаны Debug және Release нұсқаларында құрастырайық.

Мысалы, кітапхана жинағының шығарылым каталогында не болады. Бұл файлдардың ішінен бізге тек QuiLib.dll және QuiLib.lib. файлдары ғана қажет. Бұл файлдардан басқа, бізге жобаның өзінен алынған тақырып файлдары да қажет болады, бірақ бұл туралы кейінірек.

9-қадам

Осы динамикалық кітапхананы пайдаланатын жобаны жасау. жасау процесі Qt Creator шебері арқылы стандартты болады. Qt бойынша қолданбаны таңдау керек.

Жоба атауы мен орнын қосыңыз

10-қадам

Құрастыру жинағын көрсетіңіз.

11-қадам

Қолданбаның негізгі терезесінің класының атын енгізейік, сонымен қатар қай классты мұрагер ету керектігін көрсетейік. Мен QWidget таңдадым.

12-қадам

Нұсқаларды басқару жүйесін қайтадан таңдау және жобаны жасау процесін аяқтау.

13-қадам

Жоба құрылымы

Осы жобаның каталогында біз QuiLib каталогын жасаймыз, онда біз debug, release, include. каталогтарын орналастырамыз.

Бұл каталогтарда сәйкесінше жөндеу нұсқасының және шығарылым нұсқасының QuiLib.dll және QuiLib.lib құрастырылған кітапханалары болады. Қосу каталогында QuiLib.h және quilib_global.h. тақырып файлдары болады.

Яғни, жинақталған кітапхананы біреуге жалғап, пайдалансын деп тапсырған жағдайды таныстырдық.

14-қадам

Шебердің көмегімен жобаға кітапхананы қосу. Әрине, сіз бәрін қолмен жаза аласыз, бірақ егер сіз өзіңіздің қабілеттеріңізге күмәндансаңыз және бұл шындық болса, әйтпесе сіз бұл мақаланы оқымас едіңіз, онда біз шеберді қолданамыз.

15-қадам

Біз кітапхананың сыртқы екенін білеміз

16-қадам

Сондай-ақ біз оны тек Windows үшін қолданамыз. Ол Debug және Release нұсқа файлдары ешқандай отладка кітапханасының префикстері жоқ әртүрлі каталогтарда болатындай конфигурацияланған. Мен жай ғана оларды орнатпадым. .lib * кітапханаларының бірін debug немесе release каталогында көрсету жеткілікті. Басқа нұсқаға жол автоматты түрде қосылады. Сондай-ақ тақырып файлдары орналасқан каталогты көрсету керек. Бұл дәстүрлі түрде қосу** каталогы.

17-қадам

Біз толықтыруды аяқтаймыз

18-қадам

Сыртқы кітапханадан диалогтық терезені шақыратын әдісті жазу керек. Бірақ алдымен, 17. қадамындағы шебер бетінде көрген үшінші тарап кітапханасының қосылым жолдары қай жерде қосылғанын қараңыз.

Енді динамикалық кітапхананы пайдаланатын жобамыздың pro файлын қарастырайық.

WithDynamicLibrary.pro

#-------------------------------------------------
#
# Project created by QtCreator 2018-10-09T19:45:20
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = WithDynamicLibrary
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has 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

CONFIG += c++11

SOURCES += \
        main.cpp \
        Widget.cpp

HEADERS += \
        Widget.h

FORMS += \
        Widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/QuiLib/release/ -lQuiLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/QuiLib/debug/ -lQuiLib

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

Бұл файлдағы ең соңғы жолдар.

Widget.ui

Графикалық дизайнер арқылы негізгі терезеге батырманы қосамыз, оны басу арқылы сыртқы кітапханадан диалог шақырылады.

Widget.h

Түймені басу үшін ұяшықты жазайық.

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void onPushButtonClicked(); // Слот для обработки клика по кнопке

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

Widget.cpp

Ал енді біз түймені басу арқылы өңдеп, сыртқы кітапханадан диалогтық терезені шақырамыз.

#include "Widget.h"
#include "ui_Widget.h"

#include <QPushButton>

// Подключаем заголовочный файл библиотеки
#include <QuiLib/include/QuiLib.h>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // Подключаем слот к сигналу от кнопки
    connect(ui->pushButton, &QPushButton::clicked, this, &Widget::onPushButtonClicked);
}

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

void Widget::onPushButtonClicked()
{
    // Вызываем диалоговое окно
    QuiLib libWidget(this);
    libWidget.exec();
}

Оқиғаларды күтетін диалогтың ішкі циклін бастау үшін exec() әдісі арқылы диалогтық терезеге қоңырау шалу керек екенін ескеріңіз. Әйтпесе, диалог дереу жабылады, өйткені ұяшық жұмыс істейді және бұл жағдайда диалог әдіс стегінде жасалған және әдіс аяқталғаннан кейін диалог жойылады. Ал exec() әдісі диалогты жабатын сәйкес оқиға орын алғанда ғана аяқталады.

Нәтиже

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

nayk1982
  • Қаз. 9, 2018, 9:49 Т.Қ.

Хороший урок, все подробно расписано. Такой вопрос: версия Qt для дин.библиотеки не обязательно должна совпадать с версией Qt проекта, который эту библиотеку использует?

Evgenii Legotckoi
  • Қаз. 10, 2018, 2:59 Т.Ж.

Спасибо ))

Из того, что я читал в документации, следует, что библиотеки Qt бинарно совместимы по минорным версиям. То есть, если проект работал с Qt 5.6, то можно поменять библиотеки на Qt 5.7 и по прежнему всё будет работать. На практике, конечно, не всегда всё гладко проходит. То есть по идее, если динамическая библиотека использует Qt 5.6, а подключили её в проект с Qt 5.7, то должно работать. Но опять же оговорюсь, на практике может выйти иначе, особенно, если динамическая библиотека использовала Qt 5.7, а подключили проект на Qt 5.6. Как минимум мождете оказаться, что в Qt 5.6 в каком-то классе отсутствуют некоторые методы.

То есть теоретически возможно, практически, как карта ляжет.



Docent
  • Қаз. 10, 2018, 4:21 Т.Ж.

Вот какой вопрос возник: для запуска программы вне Qt приходится тащить с ехе'шником кучу dll. А для использования созданной dll не придется ли тащить с собой всё те же Qt5Core.dll, Qt5Gui.dll, Qt5Widgets.dll...? Особенно если дальнейшее использование созданной dll планируется без участия Qt

Evgenii Legotckoi
  • Қаз. 10, 2018, 4:25 Т.Ж.

Погодите. Если речь идёт о библиотеке, которая использует Qt, от естественно, что ей понадобятся все те модули, от которых зависит бибилотека. Например в данном примере используются модули Qt5Core, Qt5Gui, Qt5Widgets, соответсвенно их тоже придётся тащить с собой. Если же вы создаёте библиотеку без участия Qt, то и модули Qt не будут нужны.

Вы не можете запланировать использование библиотеки без Qt, если она использует модули Qt, но если вы отказываетесь от использования Qt в библиотеке, то тогда получаете возможность не тащить все выше перечисленные модули, поскольку библиотека от них не зависит тогда.

o
  • Қаз. 10, 2018, 4:28 Т.Ж.

Круто было бы прочитать про приложение с подключаемыми плагинами.

Evgenii Legotckoi
  • Қаз. 10, 2018, 4:31 Т.Ж.

Типо как в Qt Creator?

Самому бы интересно было о таком почитать. В данный момент я бы мог написать только о написании плагинов для Qt Designer. С этим есть некоторый опыт.

o
  • Қаз. 10, 2018, 5:46 Т.Ж.

ну типа того, создание программы, функционал которой можно расширять плагинами, и, в перспективе, создание API.

o
  • Қаз. 10, 2018, 5:48 Т.Ж.

О плагинах к QtCreator в целом, тоже интересно.

Evgenii Legotckoi
  • Қаз. 10, 2018, 5:50 Т.Ж.

Если и начинать писать о плагинах, то нужно тогда с Qt Creator начинать, там наверняка будет одинаковый принцип, но по Qt Creator хотя бы информация есть.

o
  • Қаз. 10, 2018, 9:16 Т.Ж.

наверняка, так и есть)

B
  • Қаз. 20, 2018, 12:51 Т.Қ.

В принципе у меня есть опыт реализации плагинов, могу что-нибудь накропать как будет время

Evgenii Legotckoi
  • Қаз. 21, 2018, 11:10 Т.Ж.

Это было бы здорово и полезно ))

БГ
  • Қаң. 8, 2019, 11:27 Т.Ж.

При запуске приложения библиотека должна лежать рядом с исполняемым файлом. А как сделать так, чтобы библиотека лежала в папке на уровень ниже чем сам исполняемый файл?

nayk1982
  • Қаң. 8, 2019, 9:02 Т.Қ.

QApplication::addLibraryPath()

Можно в каталоге приложения создать файл qt.conf в котором прописать пути библиотек:

[Paths]
Libraries=./lib
Plugins=./lib

Edward Wayne
  • Наурыз 4, 2019, 2:17 Т.Ж.

А можно динамическую библиотеку, скомпелированную в Visual Studio и никак не связанную с Qt, подключить в проект который разрабатывается в Qt?

Какие действия для этого нужно сделать?

Достаточно ли будет просто заменить эти строки:

#if defined(QUILIB_LIBRARY)
#  define QUILIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define QUILIBSHARED_EXPORT Q_DECL_IMPORT
#endif

на эти:

#define QUILIB_EXPORT __declspec(dllexport)

?

Evgenii Legotckoi
  • Наурыз 4, 2019, 4:22 Т.Ж.

Полагаю, что да, нужно переписать экспорт, как вы написали. А подключение в Qt проекте будет аналогичным, такженаличие пути к библиотеке и заголовочные файлы. Главное, чтобы компиляторы были одной версии.

e
  • Қар. 16, 2020, 4:32 Т.Ж.

здравствуйте! при компиляции библиотеки выскакивает окно особая программа( не удалось найти программу, укажите путь к ней), и в папке debug создается файл .dll, а .lib нет. подскажите, пожалуйста, в чем проблема.

DS
  • Ақп. 16, 2022, 6:54 Т.Ж.

Добрый день!
Очень мало информации, как писать классы с методами для компиляции в динамическую библиотеку.
Пример: в классе QuiLib дополнительно есть методы, которые могут вызываться, например

void setText(QString t) {
qlabel->setText(t);
}

то этот метод следует обьявлять как virtual, чтобы потом вызвать его где надо, верно?

Evgenii Legotckoi
  • Ақп. 17, 2022, 3:51 Т.Ж.

Нет, не верно. Модификатор virtual помечает метод класса как виртуальный, что позволяет переопределять методы при наследовании классов. К библиотекам вообще никакого отношения не имеет.

Обычно функции отдельно помечаются макросом типо QUILIBSHARED_EXPORT, но проще написать класс helper со статическими методами, ибо потом меньше проблем с линковкой и компиляцией.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз