Как создать подключаемые модули Qt (Qt plugins)
|
Базовый класс | Имя директории | Чувствительность к регистру |
---|---|---|
QAccessibleBridgePlugin | accessiblebridge | Чувствителен к регистру |
QAccessiblePlugin | accessible | Чувствителен к регистру |
QDecorationPlugin | decorations | Нечувствителен к регистру |
QFontEnginePlugin | fontengines | Нечувствителен к регистру |
QIconEnginePlugin | iconengines | Нечувствителен к регистру |
QImageIOPlugin | imageformats | Чувствителен к регистру |
QInputContextPlugin | inputmethods | Чувствителен к регистру |
QKbdDriverPlugin | kbddrivers | Нечувствителен к регистру |
QMouseDriverPlugin | mousedrivers | Нечувствителен к регистру |
QPictureFormatPlugin | pictureformats | Чувствителен к регистру |
QScreenDriverPlugin | gfxdrivers | Нечувствителен к регистру |
QScriptExtensionPlugin | script | Чувствителен к регистру |
QSqlDriverPlugin | sqldrivers | Чувствителен к регистру |
QStylePlugin | styles | Нечувствителен к регистру |
QTextCodecPlugin | codecs | Чувствителен к регистру |
Но где находится каталог plugins? Когда приложение запущено, Qt сначала просматривает каталог исполняемого файла приложения в качестве pluginsbase. Например, если приложение находится в C:\Program Files\MyApp и имеет подключаемый модуль стиля, Qt будет искать в C:\Program Files\MyApp\styles. (Смотрите QCoreApplication::applicationDirPath(), что бы выяснить, где находится исполняемый файл приложения). Qt так же будет смотреть в каталоге указанном в QLibraryInfo::location(QLibraryInfo::PluginsPath), который обычно расположен в QTDIR/plugins (где QTDIR это каталог, где установлена Qt). Если вы хотите, чтобы Qt просматривала в дополнительных местах, вы можете добавить столько путей, сколько необходимо, вызвав QCoreApplication::addLibraryPath(). И, если вы хотите установить собственный путь или пути, вы можете использовать QCoreApplication::setLibraryPaths(). Вы так же можете использовать файл qt.conf для переопределения жестко зашитых путей, которые вкомпилированы в библиотеку Qt. Для получения дополнительной информации, смотрите документацию Использование qt.conf. Еще один способ, это установить переменную окружения QT_PLUGIN_PATH перед запуском приложения. Если установлена, Qt будет искать подключаемые модули в путях (разделенных системным разделителем путей) указанных в переменной.
Предположим, что у вас есть новый класс стиля, названый MyStyle, который вы хотите сделать доступным в качестве подключаемого модуля. Требуемый код очень простой, вот объявление класса (mystyleplugin.h):
class MyStylePlugin : public QStylePlugin { public: QStringList keys() const; QStyle *create(const QString &key); };
Убедитесь, что реализация класса расположена в файле .cpp (включая объявление класса):
#include "mystyleplugin.h" QStringList MyStylePlugin::keys() const { return QStringList() << "MyStyle"; } QStyle *MyStylePlugin::create(const QString &key) { if (key.toLower() == "mystyle") return new MyStyle; return 0; } Q_EXPORT_PLUGIN2(pnp_mystyleplugin, MyStylePlugin)
(Заметьте, что QStylePlugin не чувствителен к регистру и использована прописная версия ключа в нашей реализации create(); большинство других подключаемых модулей чувствительны к регистру.)
Для драйверов баз данных, форматов изображений, текстовых кодеков и большинства других типов подключаемых модулей, не требуется явное создание объекта. Qt найдет и создаст их как требуется. Исключением являются стили, так как вы можете хотеть установить стиль в коде, явно. Чтобы добавить стиль, используйте следующий код:
QApplication::setStyle(QStyleFactory::create("MyStyle"));
Некоторые классы подключаемых модулей требуют реализации дополнительных функций. За подробностями о виртуальных функциях, которые должны быть переопределены для каждого типа подключаемого модуля, обращайтесь к документации классов.
Приложения на Qt автоматически знают какие подключаемые модули доступны, так как они хранятся в стандартных каталогах подключаемых модулей. Из-за этого приложению не требуется код для поиска и загрузки подключаемых модулей, так как Qt управляет ими автоматически.
Каталог по умолчанию для подключаемых модулей это QTDIR/plugins (где QTDIR это каталог, где установлена Qt), с подкаталогом для каждого типа подключаемых модулей, например, styles. Если вы хотите, чтобы ваше приложение использовало подключаемые модули и вы не хотите использовать стандартный путь к подключаемым модулям, заставьте ваш инсталляционный процесс определить путь, который вы хотите использовать для подключаемых модулей и сохраните его, например, используя QSettings, для считывания приложением при запуске. Приложение может вызвать QCoreApplication::addLibraryPath() с этим путем и ваши подключаемые модули будут доступны приложению. Заметьте, что последняя часть пути (например, styles) не может быть изменена.
Обычный способ, добавить подключаемый модуль в приложение - это скомпилировать его с приложением, или скомпилировать его в динамическую библиотеку и использовать ее как любую другую.
Если вы хотите, чтобы подключаемый модуль был загружаемым, тогда единственный подход - это создать подкаталог в папке с программой и положить подключаемый модуль в этот каталог. Если вы распространяете любые подключаемые модули, которые идут вместе с Qt (располагаются в каталоге plugins), вы должны скопировать подкаталог ниже plugins, в котором расположен подключаемый модуль, в корневую папку вашего приложения (т.е., не добавлять каталог plugins).
Для получения дополнительной информации относительно развертывания, смотрите документацию Развертывание приложений на Qt.
Пример Style Plugin показывает как реализовать подключаемый модуль, который расширяет базовый класс QStylePlugin.
Не только сама Qt, но так же приложения на Qt могут быть расширены с помощью подключаемых модулей. Это требует от приложения обнаружить и загрузить подключаемые модули используя QPluginLoader. В этом случае, подключаемые модули могут предоставлять произвольную функциональность и не ограничены драйверами баз данных, форматами изображений, текстовыми кодеками, стилями, и другими типами подключаемых модулей, которые расширяют функциональность Qt.
Создание расширяемых с помощью подключаемых модулей приложений включает следующие шаги:
Написание подключаемого модуля включает следующие шаги:
Например, вот определение интерфейсного класса:
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 <QStringList> #include <QImage> #include <plugandpaint/interfaces.h> class ExtraFiltersPlugin : public QObject, public FilterInterface { Q_OBJECT 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, установленных рядом.
Пример: Qt 4.3.0 не будет загружать подключаемый модуль, собранный с Qt 4.3.1.
Пример: Qt 4.3.1 не будет загружать подключаемый модуль, собранный с Qt 3.3.1.
Пример: Qt 4.3.1 загрузит подключаемые модули, собранные с Qt 4.3.0 и Qt 4.2.3.
Обоснование: Смотрите раздел Ключ сборки, ниже.
При сборке подключаемых модулей, расширяющих приложение, важно убедиться, что подключаемый модуль сконфигурирован так же как и приложение. Это значит, что если приложение было собрано в режиме релиза, подключаемый модуль так же должен быть собран в режиме релиза.
Если вы конфигурируете Qt для сборки и в режиме релиза и в режиме отладки, но собираете приложение только в режиме релиза, вы должны убедиться, что ваши подключаемые модули так же собираются в режиме релиза. По умолчанию, если доступна отладочная сборка Qt, подключаемые модули будут собраны только в режиме отладки. Что бы заставить подключаемые модули собираться в режиме релиза, добавьте следующую строку в файл проекта подключаемого модуля:
CONFIG += release
Это гарантирует совместимость подключаемого модуля с версией библиотеки, используемой в приложении.
При загрузке подключаемого модуля Qt сверяет ключ сборки каждого подключаемого модуля со своим, что бы убедиться, что только совместимые подключаемые модули загружены; любые подключаемые модули, которые сконфигурированы иначе загружены не будут.
Ключ сборки содержит следующую информацию:
Обоснование: В случаях когда различные версии одного и того же компилятора не производят совместимый код, версия компилятора так же будет присутствовать в ключе сборки.
Обоснование: Две различные конфигурации одной версии библиотеки Qt двоично не совместимы. Библиотека Qt, которая загружает подключаемый модуль использует список (отсутствующих) особенностей для определения совместим ли подключаемый модуль двоично.
Замечание: Есть случаи, когда подключаемый модуль может использовать особенности, которые доступны в двух разных конфигурациях. Тем не менее, разработчик, пишущий подключаемый модуль, должен бы знать какие особенности используются как в его подключаемом модуле, так и внутренне использованными классами Qt. Библиотека Qt будет требовать сложные особенности и запросы зависимостей и проверки при загрузке подключаемых модулей. Требование этого поместило бы ненужное бремя на разработчика, и увеличило бы накладные расходы загрузки подключаемого модуля. Для уменьшения и времени разработки, и затрат на выполнение программы используется простое сравнение строк ключей сборки.
Обоснование: Когда распространяют бинарные файлы библиотеки Qt вместе с приложением, это обеспечивает разработчика возможностью написания подключаемых модулей, которые может загрузить только та библиотека, с которой они были слинкованы.
С целью отладки возможно обходить проверку ключа сборки во времени выполнения, сконфигурировав Qt с определенным макросом препроцессора QT_NO_PLUGIN_CHECK.
Подключаемые модули могут быть слинкованы статически вместе с приложением. Если вы соберете статическую версию Qt, то возможно включение только предопределенных подключаемых модулей Qt.
Когда компилируется как статическая библиотека, тогда Qt предоставляет следующие статические подключаемые модули:
Имя подключаемого модуля | Тип | Описание |
---|---|---|
qtaccessiblecompatwidgets | Специальные возможности | Специальные возможности для поддержки виджетов Qt 3 |
qtaccessiblewidgets | Специальные возможности | Специальные возможности для виджетов Qt |
qdecorationdefault | Декорации (Выпуск Qt Extended) | Стиль по умолчанию |
qdecorationwindows | Декорации (Выпуск Qt Extended) | Стиль Windows |
qgif | Форматы изображений | GIF |
qjpeg | Форматы изображений | JPEG |
qmng | Форматы изображений | MNG |
qico | Форматы изображений | ICO |
qsvg | Форматы изображений | SVG |
qtiff | Форматы изображений | TIFF |
qimsw_multi | Методы ввода (Выпуск Qt Extended) | Переключатель метода ввода |
qwstslibmousehandler | Драйвер мыши (Выпуск Qt Extended) | мышь tslib |
qgfxtransformed | Графические драйверы (Выпуск Qt Extended) | Трансформированный экран |
qgfxvnc | Графические драйверы (Выпуск Qt Extended) | VNC |
qscreenvfb | Графические драйверы (Выпуск Qt Extended) | Виртуальный видеобуфер (frame buffer) |
qsqldb2 | драйвер SQL | IBM DB2 |
qsqlibase | драйвер SQL | Borland InterBase |
qsqlite | драйвер SQL | SQLite версии 3 |
qsqlite2 | драйвер SQL | SQLite версии 2 |
qsqlmysql | драйвер SQL | MySQL |
qsqloci | драйвер SQL | Oracle (OCI) |
qsqlodbc | драйвер SQL | Open Database Connectivity (ODBC) |
qsqlpsql | драйвер SQL | PostgreSQL |
qsqltds | драйвер SQL | Sybase Adaptive Server (TDS) |
qcncodecs | Текстовый кодек | Упрощенный китайский (Китайская народная республика) |
qjpcodecs | Текстовый кодек | Японский |
qkrcodecs | Текстовый кодек | Корейский |
qtwcodecs | Текстовый кодек | Традиционный китайский (Тайвань) |
Чтобы линковать статически вместе с этими подключаемыми модулями, вам необходимо использовать макрос Q_IMPORT_PLUGIN() в своем приложении и вам необходимо добавить требуемые подключаемые модули к вашей сборке используя QTPLUGIN. Например, в вашем main.cpp:
#include <QApplication> #include <QtPlugin> Q_IMPORT_PLUGIN(qjpeg) Q_IMPORT_PLUGIN(qgif) Q_IMPORT_PLUGIN(qkrcodecs) int main(int argc, char *argv[]) { QApplication app(argc, argv); ... return app.exec(); }
В .pro-файле вашего приложения, вам необходимо добавить следующую запись:
QTPLUGIN += qjpeg \ qgif \ qkrcodecs
Так же возможно создать свой собственный статический подключаемый модуль, следуя этим шагам:
За подробностями, как это сделать, обращайтесь к примеру Plug & Paint и связанным с ним подключаемым модулем Basic Tools.
Замечание: Если вы не используете qmake для сборки вашего приложения, вам необходимо убедиться, что определен макрос препроцессора QT_STATICPLUGIN.
Для того, чтобы ускорить загрузку и проверку подключаемых модулей, некоторая информация, собираемая при загрузке подключаемого модуля, кэшируется с помощью QSettings. Это включает информацию о том, был ли подключаемый модуль удачно загружен или нет, так что последующая операция загрузки не будет пытаться загрузить неправильный подключаемый модуль. Тем не менее, если поменяется "время последнего изменения" подключаемого модуля, запись в кэше считается устаревшей и подключаемый модуль загружается независимо от значений в кэше, которые обновляются в соответствии с новым результатом.
Это так же означает, что штамп времени должен быть обновлён каждый раз, когда подключаемый модуль или любой зависимый ресурс (такой как общая библиотека) были обновлены, так как зависимый ресурс может влиять на результат загрузки подключаемого модуля.
Иногда при разработке подключаемых модулей необходимо удалить записи из кэша подключаемых модулей. С тех пор как Qt использует QSettings для управления кэшем подключаемых модулей, размещение подключаемых модулей платформозависимо; для получения дополнительной информации о каждой платформе, смотрите документацию по QSettings.
Например, в Windows записи хранятся в реестре и пути для каждого подключаемого модуля обычно начинаются с одной из этих двух строк:
HKEY_CURRENT_USER\Software\Trolltech\OrganizationDefaults\Qt Plugin Cache 4.2.debug HKEY_CURRENT_USER\Software\Trolltech\OrganizationDefaults\Qt Plugin Cache 4.2.false
Есть несколько проблем, которые могут помешать корректно написанным подключаемым модулем работать с приложением, спроектированным для их использования. Многие из них связаны с различиями в способе сборки приложений и подключаемых модулей, часто возникая из-за разных систем сборок и процессов.
Следующая таблица содержит описание общих причин проблем, с которыми сталкиваются разработчики при создании подключаемых модулей:
Проблема | Причина | Решение |
---|---|---|
Подключаемый модуль не загружается без каких-либо сообщений, даже когда открыт непосредственно приложением. Qt Designer показывает библиотеки подключаемых модулей в своем диалоге Help|About Plugins, но ни одного подключаемого модуля не указано под каждым пунктом. | Приложение и подключаемые модули собраны в разных режимах. | Или сделайте общей одинаковую информацию о сборке, или соберите подключаемые модули в обоих режимах, отладки и релиза, добавляя debug_and_release в переменную CONFIG каждого из их файлов проектов. |
Правильный подключаемый модуль, который заменяет неправильный (или сломанный) подключаемый модуль, не может загрузиться. | Запись о подключаемом модуле в кэше подключаемых модулей указывает, что оригинальный подключаемый модуль не может быть загружен, заставляя Qt игнорировать замену. | Или убедитесь, что штамп времени подключаемого модуля обновлён, или удалите запись в кэше подключаемых модулей. |
Вы можете так же использовать переменную окружения QT_DEBUG_PLUGINS для получения диагностической информации из Qt о каждом подключаемом модуле, который она пытается загрузить. Установите эту переменную в любое не-нулевое значение, в окружении, из которого запускается ваше приложение.
Смотрите также QPluginLoader, QLibrary, и Plug & Paint Example.
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Торговые марки | Qt 4.5.3 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |