Как создать плагины Qt
Qt предоставляет два API для создания плагинов:
- API высокого уровня для написания расширений самого Qt: пользовательские драйверы баз данных, форматы изображений, кодеки текста, пользовательские стили и т. д.
- API низкого уровня для расширения приложений Qt.
Например, если вы хотите написать подкласс пользовательского QStyle и хотите, чтобы приложения Qt загружали его динамически, вы бы использовали API высокого уровня.
Поскольку API высокого уровня построен поверх API низкого уровня, некоторые проблемы характерны для обоих.
Если вы хотите предоставить плагины для использования с Qt Designer, см. документацию модуля Qt Designer.
Темы:
API высокого уровня: написание расширений Qt
Написание плагина, расширяющего сам Qt, достигается путем наследования от соответствующего базового класса плагина, реализации нескольких функций и добавления макроса.
Существует несколько базовых классов плагинов. Производные плагины по умолчанию хранятся в подкаталогах стандартного каталога плагинов. Qt не найдет плагины, если они не хранятся в соответствующем каталоге.
Следующая таблица обобщает базовые классы плагинов. Некоторые классы являются приватными и поэтому не документированы. Вы можете их использовать, но нет гарантии совместимости с будущими версиями Qt.
| Базовый класс | Имя каталога | Модуль Qt | Чуткость к регистру |
|---|---|---|---|
| QAccessibleBridgePlugin | accessiblebridge |
Qt GUI | Чутк к регистру |
| QImageIOPlugin | imageformats |
Qt GUI | Чутк к регистру |
| QPictureFormatPlugin (устарело) | pictureformats |
Qt GUI | Чутк к регистру |
| QBearerEnginePlugin | bearer |
Qt Network | Чутк к регистру |
| QPlatformInputContextPlugin | platforminputcontexts |
Qt Platform Abstraction | Нечувствителен к регистру |
| QPlatformIntegrationPlugin | platforms |
Qt Platform Abstraction | Нечувствителен к регистру |
| QPlatformThemePlugin | platformthemes |
Qt Platform Abstraction | Нечувствителен к регистру |
| QPlatformPrinterSupportPlugin | printsupport |
Qt Print Support | Нечувствителен к регистру |
| QSGContextPlugin | scenegraph |
Qt Quick | Чутк к регистру |
| QSqlDriverPlugin | sqldrivers |
Qt SQL | Чутк к регистру |
| QIconEnginePlugin | iconengines |
Qt SVG | Нечувствителен к регистру |
| QAccessiblePlugin | accessible |
Qt Widgets | Чутк к регистру |
| QStylePlugin | styles |
Qt Widgets | Нечувствителен к регистру |
Если у вас есть новый класс стиля под названием MyStyle, который вы хотите сделать доступным как плагин, класс должен быть определен следующим образом (mystyleplugin.h):
class MyStylePlugin : public QStylePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "mystyleplugin.json")
public:
QStyle *create(const QString &key);
}; Убедитесь, что реализация класса находится в файле .cpp:
#include "mystyleplugin.h"
QStyle *MyStylePlugin::create(const QString &key)
{
if (key.toLower() == "mystyle")
return new MyStyle;
return 0;
} (Обратите внимание, что QStylePlugin нечувствителен к регистру, и в нашей реализации create() используется нижний регистр ключа; большинство других плагинов чувствительны к регистру.)
Кроме того, для большинства плагинов требуется файл json (mystyleplugin.json) содержащий метаданные, описывающие плагин. Для плагинов стиля он просто содержит список стилей, которые можно создать с помощью плагина:
{ "Keys": [ "mystyleplugin" ] } Тип информации, который нужно предоставить в файле json, зависит от плагина, пожалуйста, обратитесь к документации класса для получения подробной информации о необходимой информации в файле.
Для драйверов баз данных, форматов изображений, кодеков текста и большинства других типов плагинов явного создания объекта не требуется. Qt найдет и создаст их по мере необходимости. Стиль является исключением, так как вы можете захотеть явно установить стиль в коде. Для применения стиля используйте такой код:
QApplication::setStyle(QStyleFactory::create("MyStyle")); Некоторые классы плагинов требуют реализации дополнительных функций. См. документацию класса для получения подробной информации о виртуальных функциях, которые необходимо переопределить для каждого типа плагина.
Пример плагина стиля демонстрирует, как реализовать плагин, расширяющий базовый класс QStylePlugin.
API низкого уровня: расширение приложений Qt
Не только сам Qt, но и приложения Qt могут быть расширены с помощью плагинов. Для этого приложение должно обнаруживать и загружать плагины с помощью QPluginLoader. В этом контексте плагины могут предоставлять произвольную функциональность и не ограничиваются драйверами баз данных, форматами изображений, кодеками текста, стилями и другими типами плагинов, расширяющими функциональность Qt.
Для того, чтобы сделать приложение расширяемым с помощью плагинов, необходимо выполнить следующие действия:
- Определите набор интерфейсов (классы с только чистыми виртуальными функциями), используемые для общения с плагинами.
- Используйте макрос Q_DECLARE_INTERFACE(), чтобы сообщить системе метаобъектов Qt об интерфейсе.
- Используйте QPluginLoader в приложении для загрузки плагинов.
- Используйте qobject_cast(), чтобы проверить, реализует ли плагин заданный интерфейс.
Написание плагина включает следующие шаги:
- Объявите класс плагина, который наследуется от QObject и от интерфейсов, которые плагин хочет предоставить.
- Используйте макрос Q_INTERFACES(), чтобы сообщить системе метаобъектов Qt об интерфейсах.
- Экспортируйте плагин с помощью макроса Q_PLUGIN_METADATA().
- Соберите плагин с помощью соответствующего файла
.pro.
Например, вот определение класса интерфейса:
class FilterInterface
{
public:
virtual ~FilterInterface() {}
virtual QStringList filters() const = 0;
virtual QImage filterImage(const QString &filter, const QImage &image,
QWidget *parent) = 0;
}; Вот определение класса плагина, который реализует этот интерфейс:
#include <QObject>
#include <QtPlugin>
#include <QStringList>
#include <QImage>
#include <plugandpaint/interfaces.h>
class ExtraFiltersPlugin : public QObject, public FilterInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json")
Q_INTERFACES(FilterInterface)
public:
QStringList filters() const;
QImage filterImage(const QString &filter, const QImage &image,
QWidget *parent);
}; Документация к примеру "Plug & Paint" подробно объясняет этот процесс. Также см. Создание пользовательских виджетов для Qt Designer для получения информации о проблемах, специфичных для Qt Designer. Вы также можете взглянуть на пример плагина "Echo", который является более тривиальным примером реализации плагина, расширяющего приложения Qt. Обратите внимание, что QCoreApplication должен быть инициализирован перед загрузкой плагинов.
Поиск плагинов
Приложения Qt автоматически знают, какие плагины доступны, поскольку плагины хранятся в стандартных подкаталогах плагинов. Поэтому приложениям не нужен код для поиска и загрузки плагинов, так как Qt обрабатывает их автоматически.
Во время разработки каталог для плагинов находится в QTDIR/plugins (где QTDIR - это каталог, где установлен Qt), при этом каждый тип плагина находится в подкаталоге для этого типа, например, styles. Если вы хотите, чтобы ваши приложения использовали плагины, и не хотите использовать стандартный путь к плагинам, пусть ваш процесс установки определит используемый вами путь для плагинов и сохранит его, например, используя QSettings, чтобы приложение читало его при запуске. Затем приложение может вызвать QCoreApplication::addLibraryPath() с этим путем, и ваши плагины будут доступны для приложения. Обратите внимание, что конечная часть пути (например, styles) не может быть изменена.
Если вы хотите, чтобы плагин был загружаемым, один из подходов - создать подкаталог в приложении и поместить плагин в этот каталог. Если вы распространяете любые плагины, которые поставляются с Qt (те, что находятся в каталоге plugins), вы должны скопировать подкаталог, в котором находится плагин, в корневой каталог вашего приложения (т. е. не включайте каталог plugins).
Дополнительную информацию о развертывании см. в документации развертывания приложений Qt и развертывания плагинов.
Статические плагины
Обычный и наиболее гибкий способ включения плагина в приложение - скомпилировать его в динамическую библиотеку, которая поставляется отдельно, и обнаруживается и загружается во время выполнения.
Плагины могут быть статически связаны с вашим приложением. Если вы создаете статическую версию Qt, это единственный вариант включения предопределенных плагинов Qt. Использование статических плагинов делает развертывание менее подверженным ошибкам, но имеет недостаток, заключающийся в том, что никакая функциональность из плагинов не может быть добавлена без полной пересборки и повторного распространения приложения.
Для статической связи с плагинами необходимо добавить необходимые плагины к вашей сборке, используя QTPLUGIN.
В файле .pro вашего приложения необходима следующая запись:
QTPLUGIN += qjpeg \
qgif \
qkrcodecs qmake автоматически добавляет плагины в QTPLUGIN, которые обычно необходимы для используемых модулей Qt (см. QT), в то время как более специализированные плагины нужно добавлять вручную. Список автоматически добавляемых плагинов по умолчанию можно переопределить по типу. Например, чтобы связать минимальный плагин вместо стандартного адаптера платформы Qt, используйте:
QTPLUGIN.platforms = qminimal
Если вы хотите, чтобы ни стандартный, ни минимальный плагин QPA не подключался автоматически, используйте:
QTPLUGIN.platforms = -
Значения по умолчанию настроены для оптимального опыта "из коробки", но могут ненужно раздувать приложение. Рекомендуется проверить командную строку компоновщика, сгенерированную qmake, и исключить ненужные плагины.
Детали статической связи плагинов
Для того, чтобы статические плагины фактически были подключены и инициализированы, также нужны макросы Q_IMPORT_PLUGIN(), но они автоматически генерируются qmake и добавляются в ваш проект приложения.
Если вы не хотите, чтобы все плагины, добавленные в QTPLUGIN, автоматически подключались, удалите import_plugins из переменной CONFIG:
CONFIG -= import_plugins
Создание статических плагинов
Также можно создать собственные статические плагины, выполнив следующие шаги:
- Добавьте
CONFIG += staticв файл.proвашего плагина. - Используйте макрос Q_IMPORT_PLUGIN() в вашем приложении.
- Используйте макрос Q_INIT_RESOURCE() в вашем приложении, если плагин содержит файлы qrc.
- Свяжите ваше приложение с вашей библиотекой плагинов, используя
LIBSв файле.pro.
См. пример Подключение и рисование и связанный с ним плагин Основные инструменты для получения подробной информации об этом.
Примечание: Если вы не используете qmake для построения своего плагина, вам необходимо убедиться, что макрос препроцессора QT_STATICPLUGIN определен.
Развёртывание и отладка плагинов
Документ Развёртывание плагинов описывает процесс развёртывания плагинов с приложениями и их отладку при возникновении проблем.
См. также QPluginLoader, QLibrary и Пример Подключения и рисования.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/plugins-howto.html