Как создать плагины 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 Plugin, который является более простым примером того, как реализовать плагин, расширяющий приложения Qt. Обратите внимание, что QCoreApplication должен быть инициализирован до загрузки плагинов.
Поиск плагинов
Приложения Qt автоматически знают, какие плагины доступны, потому что плагины хранятся в стандартных подкаталогах плагинов. Благодаря этому приложениям не требуется какой-либо код для поиска и загрузки плагинов, так как Qt обрабатывает их автоматически.
Во время разработки каталог для плагинов – это QTDIR/plugins (где QTDIR – это каталог, где установлен Qt), с каждым типом плагина в подкаталоге для этого типа, например, styles. Если вы хотите, чтобы ваши приложения использовали плагины, и не хотите использовать стандартный путь к плагинам, задайте путь к плагинам в процессе установки и сохраните его, например, с помощью QSettings, чтобы приложение могло его прочитать при запуске. Затем приложение может вызвать QCoreApplication::addLibraryPath() с этим путём, и ваши плагины будут доступны для приложения. Обратите внимание, что последняя часть пути (например, styles) изменить нельзя.
Если вы хотите, чтобы плагин можно было загрузить, один из подходов – создать подкаталог в приложении и поместить плагин в этот каталог. Если вы распространяете какие-либо плагины, которые входят в состав Qt (те, которые находятся в каталоге plugins), вы должны скопировать подкаталог под 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.0/plugins-howto.html