Qtプラグインの作り方

Qtはプラグインを作成するための2つのAPIを提供しています:

  • Qt プラグインを作成するための 2 つの API が用意されています: Qt プラグインを作成するための高レベル API。
  • Qt アプリケーションを拡張するための低レベル API。

例えば、QStyle のサブクラスを作成し、Qt アプリケーションに動的に読み込ませたい場合は、高レベル API を使用します。

上位APIは下位APIの上に構築されているため、いくつかの問題は両方に共通です。

Qt Widgets Designer で使用するプラグインを提供したい場合は、Creating Custom Widget Plugins を参照してください。

高レベル API:Qt 拡張機能の記述

Qt 自体を拡張するプラグインを作成するには、適切なプラグイン基底クラスをサブクラス化し、いくつかの関数を実装し、マクロを追加します。

プラグインの基本クラスはいくつかあります。派生プラグインは、デフォルトでは標準プラグインディレクトリのサブディレクトリに格納されます。プラグインが適切なディレクトリに格納されていない場合、Qtはプラグインを見つけられません。

以下の表は、プラグインの基本クラスをまとめたものです。いくつかのクラスはプライベートなので、ドキュメント化されていません。それらを使用することはできますが、それ以降の Qt バージョンとの互換性は約束されていません。

基本クラスディレクトリ名Qt モジュール大文字と小文字の区別
QAccessibleBridgePluginaccessiblebridgeQt GUI大文字小文字を区別する
QImageIOPluginimageformatsQt GUI大文字小文字を区別
QPictureFormatPlugin (廃止予定)pictureformatsQt GUI大文字小文字を区別
QBearerEnginePluginbearerQt Networkケースセンシティブ
QPlatformInputContextPluginplatforminputcontextsQt プラットフォーム抽象化大文字小文字を区別しない
QPlatformIntegrationPluginplatformsQt プラットフォーム抽象化大文字小文字を区別しない
QPlatformThemePluginplatformthemesQt プラットフォーム抽象化大文字小文字を区別しない
QPlatformPrinterSupportPluginprintsupportQt Print Support大文字小文字を区別しない
QSGContextPluginscenegraphQt Quick大文字小文字を区別
QSqlDriverPluginsqldriversQt SQL大文字小文字を区別
QIconEnginePluginiconenginesQt SVG大文字小文字を区別しない
QAccessiblePluginaccessibleQt Widgets大文字小文字を区別
QStylePluginstylesQt Widgets大文字小文字を区別しない

JsonViewer という新しいドキュメント・ビューア・クラスをプラグインとして利用できるようにする場合、そのクラスは次のように定義する必要があります (jsonviewer.h):

class JsonViewer : public ViewerInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface/1.0" FILE "jsonviewer.json")
    Q_INTERFACES(ViewerInterface)
public:
    JsonViewer();
    ~JsonViewer() override;
private:
    bool openJsonFile();

    QTreeView *m_tree;
    QListWidget *m_toplevel = nullptr;
    QJsonDocument m_root;

    QPointer<QLineEdit> m_searchKey;
};

クラス実装が.cpp ファイルにあることを確認してください:

JsonViewer::JsonViewer()
{
    connect(this, &AbstractViewer::uiInitialized, this, &JsonViewer::setupJsonUi);
}

void JsonViewer::init(QFile *file, QWidget *parent, QMainWindow *mainWindow)
{
    AbstractViewer::init(file, new QTreeView(parent), mainWindow);
    m_tree = qobject_cast<QTreeView *>(widget());
}

さらに、プラグインを説明するメタデータを含むjsonファイル(jsonviewer.json)が、ほとんどのプラグインに必要です。ドキュメント・ビューア・プラグインの場合は、単にビューア・プラグインの名前が含まれます。

{ "Keys": [ "jsonviewer" ] }

jsonファイルで提供する必要がある情報のタイプは、プラグインに依存します。ファイルに含める必要がある情報の詳細については、クラスのドキュメントを参照してください。

データベースドライバ、画像フォーマット、テキストコーデック、その他ほとんどのプラグインでは、明示的にオブジェクトを作成する必要はありません。Qtが必要に応じてそれらを見つけ、作成します。

プラグインクラスは、追加関数を実装する必要があるかもしれません。プラグインの種類ごとに再実装が必要な仮想関数の詳細については、クラスのドキュメントを参照してください。

ドキュメント・ビューア・デモでは、構造化されたファイルの内容を表示するプラグインの実装方法を示しています。そのため、各プラグインは以下の仮想関数を再実装しています。

  • プラグインを識別する
  • サポートしている MIME タイプを返す
  • 表示するコンテンツがあるかどうかと
  • コンテンツの表示方法
    QString viewerName() const override { return QLatin1StringView(staticMetaObject.className()); };
    QStringList supportedMimeTypes() const override;
    bool hasContent() const override;
    bool supportsOverview() const override { return true; }

低レベル 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() マクロを使用してプラグインをエクスポートします。

例えば、インターフェイスクラスの定義です:

class ViewerInterface : public AbstractViewer
{
public:
    virtual ~ViewerInterface() = default;
};

これがインターフェイス宣言です:

#define ViewerInterface_iid "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface/1.0"
Q_DECLARE_INTERFACE(ViewerInterface, ViewerInterface_iid)

Qt Widgets Designer 固有の問題については、 Qt Widgets Designer 用のカスタム ウィジェットの作成も参照してください。

プラグインの場所

プラグインは標準のプラグイン・サブディレクトリに格納されているため、Qtアプリケーションはどのプラグインが利用可能かを自動的に知ることができます。プラグインは標準のプラグインサブディレクトリに格納されているため、Qtアプリケーションはプラグインを自動的に知ることができます。

開発中、プラグイン用のディレクトリはQTDIR/plugins (QTDIR は Qt がインストールされているディレクトリ) で、プラグインの種類ごとにサブディレクトリが用意されています。例えば、styles です。アプリケーションでプラグインを使用したいが、標準のプラグインパスを使用したくない場合は、インストールプロセスでプラグインに使用するパスを決定し、アプリケーションの実行時に読み込めるように、例えばQSettings を使用してパスを保存します。アプリケーションは、このパスを使用してQCoreApplication::addLibraryPath() を呼び出すことができ、プラグインはアプリケーションから利用できるようになります。パスの最後の部分(たとえばstyles )は変更できないことに注意してください。

プラグインをロード可能にしたい場合は、アプリケーションの下にサブディレクトリを作成し、その中にプラグインを配置するという方法があります。Qt に付属しているプラグイン(plugins ディレクトリにあるもの)を配布する場合は、プラグインがあるplugins 以下のサブディレクトリをアプリケーションのルートフォルダにコピーする必要があります(つまり、plugins ディレクトリは含めないでください)。

デプロイの詳細については、Qt アプリケーションのデプロイと プラグインのデプロイのドキュメントを参照してください。

静的プラグイン

アプリケーションにプラグインを含める最も柔軟な方法は、プラグインをダイナミックライブラリにコンパイルすることです。

プラグインは静的にアプリケーションにリンクすることができます。Qt の静的バージョンをビルドする場合、これが Qt の定義済みプラグインを含めるための唯一の選択肢です。静的なプラグインを使用すると、デプロイ時にエラーが発生しにくくなりますが、アプリケーションを完全にリビルドして再配布しなければ、プラグインから機能を追加できないという欠点があります。

CMake と qmake は、使用する Qt モジュールで一般的に必要とされるプラグインを自動的に追加しますが、より特殊なプラグインは手動で追加する必要があります。自動的に追加されるプラグインのデフォルトリストは、タイプごとにオーバーライドすることができます。

デフォルトは、すぐに使えるように最適化されていますが、不必要にアプリケーションを肥大化させる可能性があります。リンカー・コマンド・ラインを検査し、不要なプラグインを削除することをお勧めします。

静的プラグインが実際にリンクされ、インスタンス化されるようにするには、Q_IMPORT_PLUGIN ()マクロもアプリケーション・コードに必要ですが、これらはビルド・システムによって自動的に生成され、アプリケーション・プロジェクトに追加されます。

CMakeで静的プラグインをインポートする

CMakeプロジェクトでプラグインを静的にリンクするには、qt_import_pluginsコマンドを呼び出す必要があります。

例えば、Linuxlibinput プラグインはデフォルトではインポートされません。次のコマンドでインポートします:

qt_import_plugins(myapp INCLUDE Qt::QLibInputPlugin)

デフォルトの Qt Platform Adaptation プラグインの代わりに最小限の Platform Integration プラグインをリンクするには、次のようにします:

qt_import_plugins(myapp
    INCLUDE_BY_TYPE platforms Qt::MinimalIntegrationPlugin
)

もう一つの典型的な使用例は、特定のimageformats プラグインのセットだけをリンクすることです:

qt_import_plugins(myapp
    INCLUDE_BY_TYPE imageformats Qt::QJpegPlugin Qt::QGifPlugin
)

imageformats 、どのプラグインともリンクしないようにしたい場合は、次のようにする:

qt_import_plugins(myapp
    EXCLUDE_BY_TYPE imageformats
)

デフォルトのプラグインの追加をオフにしたい場合は、qt_import_pluginsの NO_DEFAULT

qmakeで静的プラグインをインポートする

qmakeプロジェクトでは、QTPLUGIN を使って必要なプラグインをビルドに追加する必要があります:

QTPLUGIN += qlibinputplugin

例えば、デフォルトのQt Platform Adaptationプラグインの代わりにminimalプラグインをリンクするには、次のようにします:

QTPLUGIN.platforms = qminimal

デフォルトの QPA プラグインと最小限の QPA プラグインのどちらも自動的にリンクさせたくない場合は、次のように使用します:

QTPLUGIN.platforms = -

QTPLUGINに追加されたすべてのプラグインを自動的にリンクさせたくない場合は、CONFIG 変数からimport_plugins を削除してください:

CONFIG -= import_plugins

静的プラグインの作成

以下の手順に従って、独自のスタティック・プラグインを作成することも可能です:

  1. CMakeLists.txtqt_add_pluginコマンドにSTATIC オプションを渡します。qmake プロジェクトの場合、プラグインの.pro ファイルにCONFIG += static を追加します。
  2. アプリケーションでQ_IMPORT_PLUGIN() マクロを使用します。
  3. プラグインが qrc ファイルを同梱している場合は、アプリケーションでQ_INIT_RESOURCE() マクロを使用します。
  4. CMakeLists.txt または.pro ファイルのLIBStarget_link_libraries を使用して、アプリケーションとプラグイン・ライブラリをリンクします。

この方法の詳細については、Plug & Paint のサンプルと、関連するBasic Toolsプラグインを参照してください。

注意: プラグインのビルドにCMakeやqmakeを使用していない場合は、QT_STATICPLUGIN プリプロセッサマクロが定義されていることを確認する必要があります。

プラグインのロード

プラグインの種類(静的または共有)とオペレーティングシステムは、プラグインを見つけてロードするための特定のアプローチを必要とします。プラグインをロードするための抽象化を実装しておくと便利です。

void ViewerFactory::loadViewerPlugins()
{
    if (!m_viewers.isEmpty())
        return;

QPluginLoader::staticInstances() は、静的にリンクされた各プラグインへのポインタを持つQObjectList を返します。

    // Load static plugins
    const QObjectList &staticPlugins = QPluginLoader::staticInstances();
    for (auto *plugin : staticPlugins)
        addViewer(plugin);

共有プラグインはデプロイメント・ディレクトリに存在するため、OS固有の処理が必要になる場合があります。

   // 共有プラグインをロードする   QDirpluginsDir=QDir(QApplication::applicationDirPath());#if defined(Q_OS_WINDOWS)pluginsDir.cd("app"_L1);#elif defined(Q_OS_DARWIN) if(pluginsDir.dirName()== "MacOS"_L1) { pluginsDir.cdUp(); pluginsDir.cdUp(); }#endif const autoentryList=pluginsDir.entryList(QDir::Files);for(constQString&fileName: entryList) { の場合        QPluginLoaderloader(pluginsDir.absoluteFilePath(fileName));        QObject*plugin =loader.instance();if(plugin) addViewer(plugin);#if 0 else            qDebug() << loader.errorString();
#endif} }

プラグインのデプロイとデバッグ

プラグインのデプロイ」ドキュメントでは、アプリケーションとプラグインをデプロイするプロセスと、問題が発生したときのデバッグについて説明します。

QPluginLoaderQLibraryも参照してください

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.