Spec-Zone.ru › Qt 5.9

Как создать плагины 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 Регистрозависимый
QAudioSystemPlugin audio Qt Multimedia Регистронезависимый
QDeclarativeVideoBackendFactoryInterface video/declarativevideobackend Qt Multimedia Регистронезависимый
QGstBufferPoolPlugin video/bufferpool Qt Multimedia Регистронезависимый
QMediaPlaylistIOPlugin playlistformats Qt Multimedia Регистронезависимый
QMediaResourcePolicyPlugin resourcepolicy Qt Multimedia Регистронезависимый
QMediaServiceProviderPlugin mediaservice Qt Multimedia Регистронезависимый
QSGVideoNodeFactoryPlugin video/videonode Qt Multimedia Регистронезависимый
QBearerEnginePlugin bearer Qt Network Регистрозависимый
QPlatformInputContextPlugin platforminputcontexts Qt Platform Abstraction Регистронезависимый
QPlatformIntegrationPlugin platforms Qt Platform Abstraction Регистронезависимый
QPlatformThemePlugin platformthemes Qt Platform Abstraction Регистронезависимый
QGeoPositionInfoSourceFactory position Qt Positioning Регистрозависимый
QPlatformPrinterSupportPlugin printsupport Qt Print Support Регистронезависимый
QSGContextPlugin scenegraph Qt Quick Регистрозависимый
QScriptExtensionPlugin script Qt Script Регистрозависимый
QSensorGesturePluginInterface sensorgestures Qt Sensors Регистрозависимый
QSensorPluginInterface sensors Qt Sensors Регистрозависимый
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.

Чтобы сделать приложение расширяемым с помощью плагинов, выполните следующие шаги:

  1. Определите набор интерфейсов (классы только с чистыми виртуальными функциями), используемые для связи с плагинами.
  2. Используйте макрос Q_DECLARE_INTERFACE(), чтобы сообщить системе метаобъектов Qt об интерфейсе.
  3. Используйте QPluginLoader в приложении для загрузки плагинов.
  4. Используйте qobject_cast(), чтобы проверить, реализует ли плагин данный интерфейс.

Написание плагина включает в себя следующие шаги:

  1. Объявите класс плагина, который наследуется от QObject и от интерфейсов, которые плагин хочет предоставить.
  2. Используйте макрос Q_INTERFACES(), чтобы сообщить системе метаобъектов Qt об интерфейсах.
  3. Экспортируйте плагин, используя макрос Q_PLUGIN_METADATA().
  4. Соберите плагин, используя подходящий файл .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) изменить нельзя.

END_OF_DOCUMENT_MARKER

Если вы хотите, чтобы плагин был загружаемым, один из способов — создать подкаталог в приложении и поместить плагин в этот каталог. Если вы распространяете плагины, поставляемые с 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

Создание статических плагинов

Также возможно создать собственные статические плагины, выполнив следующие шаги:

  1. Добавьте CONFIG += static в файл .pro вашего плагина.
  2. Используйте макрос Q_IMPORT_PLUGIN() в вашем приложении.
  3. Используйте макрос Q_INIT_RESOURCE() в вашем приложении, если плагин содержит файлы qrc.
  4. Свяжите ваше приложение с библиотекой плагина, используя LIBS в файле .pro.

См. пример Plug & Paint и соответствующий плагин Basic Tools для получения подробной информации о том, как это сделать.

Примечание: Если вы не используете qmake для сборки своего плагина, вам необходимо убедиться, что макрос препроцессора QT_STATICPLUGIN определён.

Развертывание и отладка плагинов

Документ Развертывание плагинов описывает процесс развертывания плагинов с приложениями и их отладку при возникновении проблем.

См. также QPluginLoader, QLibrary и Пример Plug & Paint.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.9/plugins-howto.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API