Spec-Zone.ru › Qt 5.6

Как создавать плагины 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"));

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

Пример плагина стиля Style Plugin Example демонстрирует реализацию плагина, расширяющего базовый класс 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 Example, который является более простым примером того, как реализовать плагин, расширяющий приложения 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/archives/qt-5.6/plugins-howto.html

Spec-Zone.ru

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