Qt 5のプラグイン機構(1)--Qtフレームにおけるプラグインロード機構の概要


概要
QtのソースコードはQFactory、QPlugin、Qの3つのクラスを通じてQtプラグインのロードメカニズムを実現しています。このメカニズムは特定の種類のプラグインをロードするために使用できます。例えば、QPlatform Integration Factory\QPlatform Integration Plugin\QPlatform Integrationを通じて
3つのクラスはプラットフォーム種類のQPAプラグインのロードを実現できます。QPlatform InputContact Factory\QPlatform InputControugin\
QPlatform Input Contectの3つのクラスは、入力メソッドプラグイン(InputContect)のロードを実現することができます。
下から上にQtプラグインのロードメカニズムを紹介します。
実装プラグイン:QクラスとQPluginクラスは、まず、Qクラス(またはそのサブクラス)が具体的な機能を実現し、彼はプラグインの本体であり、異なる種類のプラグインが異なる機能を実現します。
QPlugin類(またはそのサブクラス)は、プラグインのインターフェースクラスであり、一般的には一つの方法を実現するだけで、creatは、
class QPlugin 
{
    ...
    Q * creat(...) ;    //     Q     ,              ,
                    //        new    Q     ,      
}
QPlugin類は主にQtフレーム自体でプラグインをロードします。
アドイン:QFactoryLoader類の他にもう一つの種類があります。プラグインのロードと関係があります。このクラスはQFactoryLoaderです。私たちは今はこの種類のinstance()に関心を持っています。
QFactoryLoader::QObject *instance(int index)
QFactoryLoaderクラスは、ライブラリリストを維持します。indexは、ロードするプラグインが属するライブラリのリストにあるインデックスです。instanceは、1つのライブラリに戻ります。
QOjbectクラスまたはそのサブクラスのポインタは、一般にこのポインタをQPluginタイプにマッピングします。
このように、Qtフレームにプラグインをロードするには、まずQFactoryLoaderを呼び出す必要があります。:instanceは、プラグインに対応するものを返します。
QPluginポインタは、このポインタでQPlugin::creat(...)を呼び出すと、プラグイン本体が得られます。
クラスQの一例。
プラグインをロードするショートカット関数は次にq LoadPluginとq LoadPlugin 1という2つのテンプレート関数の実装を見に行きます。両者の機能上の主な違いは後者がプラグインをロードする時のパラメータを設定することができます。
これらの2つのテンプレート関数を使用して、プラグインをすばやく読み込み、その例を取得することができます。
この2つのテンプレートを使用する場合、テンプレートタイプパラメータPlugin Interfaceは、Q(プラグイン本体クラス)、タイプパラメータFactory Interfaceとして充填されます。
QPlugin類に充填すること。
template 
    PluginInterface *qLoadPlugin(const QFactoryLoader *loader, const QString &key)
{
    const int index = loader->indexOf(key);    //                          
    if (index != -1) {
        QObject *factoryObject = loader->instance(index);    //         
        if (FactoryInterface *factory = qobject_cast(factoryObject))
            if (PluginInterface *result = factory->create(key))
                return result;    //         
    }
    return 0;
}

template 
PluginInterface *qLoadPlugin1(const QFactoryLoader *loader,
                              const QString &key,
                              const Parameter1 ¶meter1)
{
    const int index = loader->indexOf(key);
    if (index != -1) {
        QObject *factoryObject = loader->instance(index);
        if (FactoryInterface *factory = qobject_cast(factoryObject))
            if (PluginInterface *result = factory->create(key, parameter1))
                return result;
    }
    return 0;
}
プラグイン生産者:QFactory類は最後にQFactory類を見にきました。Qtのプラグインローディング機構の中で一番上のクラスです。この類は主に2つのタイプを実現します。
つの静的な方法(creatにもっと関心があります。)そして静的なものです。その定義は大体以下の通りです。
class QFactory
{
public:
    static QStringList keys(...) ;    //     Q              ,
                    //                  ,           
                    //             。  QPlatformInputContextFactory::keys(...)
                    //                。
    
    static Q * creat(...) ;    //     Q     (         )    
}
QFactory::creat(...)関数では、環境変数を検出するなどして、対応するプラグインに関するキーワードを取得し、このキーワードを使用します。
q LoadPlugin/q LoadPlugin 1または同様の方法でプラグインをロードし、最後にプラグインエンティティクラスに戻ります。
QFactoryクラスは、ある種類、または特定の機能のプラグインに対応します。例えば、QPlatform Integration Factoryは、「生産」プラットフォームタイプのプラグインに使用されます。
QPlatform InputContect Factoryは、「製造」入力法のプラグインに使用されます。一般的には、QFactory類には実際のメンバー変数はなく、いくつかしかありません。
静的な方法ですので、Qtアプリケーションでは、このクラスを具体化する必要はなく、直接的にこのクラスの静的な方法を使用します。
Qtはまた、QFactoryクラスごとにQFactoryLoaderオブジェクトをバインドしています。このオブジェクトは、このカテゴリのプラグインをロードするのを専門に担当しています。
Qtフレームの最上階にプラグインをロードするには、対応するQFactory類とだけ付き合えばいいです。例えば、Qtアプリケーション初期化中に、自分が発見されます。
入力プラグインが必要になります。直接にQPlatform InputContactFactoryを呼び出すことができます。creat(...)は入力メソッドのプラグインを作成します。このプラグインのロード過程の詳細を管理しなくてもいいです。
戻ってきたこの入力方式のプラグインはいったい何ですか?ibusですか?それともfcitxですか?これらは完全にユーザーによって環境変数QTuIMuMODLEで指定されています。
 QPlatform InputContect Factory:create()メソッドではこの環境変数を検出します。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
付1:QtアプリケーションのプラットフォームタイププラグインQPlatform Integrationのロードプロセス
今しばらく焦点をQGiAppliation Privateに移します。:plotform Integration()で、この方法の定義は以下の通りです。
    static QPlatformIntegration *platform_integration;
    static QPlatformIntegration *platformIntegration()
    { return platform_integration; }
プラットフォームが現在の運行プラットフォームを指していることが分かりますが、この代表プラットフォームのメンバーはどこで初期化されますか?
QGuiAppliationクラス(GUIアプリケーション毎にその例があります)のコンストラクタでは、QGuiAppliation Private類のinit()メソッドを呼び出します。
QGuiAppliation Private:initはまたQGuiAppliation Privateを呼び出します:createPlatform Integration()は、後者は読みます。
QT_____________________________________________________________________________________________________________
init upplication.cppファイルの中に、この関数はqtbase/src/gui/ケネル/qggatipplication.cppファイルと定義されています。
GuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name,
arguments, argc, argv, platformPluginPath);
....
QPlatform Integration Factory:createでは、次のようにプラットフォームプラグインをロードします。
QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))
loadIntegration関数は、qtbase/src/gui/kersnel/QPlatform Integration Factory.cppに定義されており、この関数の役割と実現方法はテンプレート関数qLoadPluginの実装と類似している。
static inline QPlatformIntegration *loadIntegration(QFactoryLoader *loader, const QString &key, const QStringList ¶meters, int &argc, char ** argv)
{
    const int index = loader->indexOf(key);
    if (index != -1) {

    // factory              , QLinuxFbIntegrationPlugin ;
    //      creat          QPlatformIntegration        ,
    //            QGuiApplicationPrivate::platform_integration, 
    //                .
    //       ,        QPA    ,      QPlatformIntegrationPlugin    QPlatformIntegration   。
        if (QPlatformIntegrationPlugin *factory = qobject_cast(loader->instance(index)))    
            if (QPlatformIntegration *result = factory->create(key, parameters, argc, argv))
                return result;
    }
    return 0;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
付2:Qtアプリケーションの入力メソッドプラグインQPlatform InputContectのロードプロセス
Linux xcbプラットフォームまたはlinuxfbプラットフォームは、プラットフォームプラグイン(QXcbIntegrationまたはQLinuxFbIntegrationクラス)のinitialize()関数によって通過されます。
QPlatform InputContect Factoryを呼び出します。プラットフォームの入力プラグインを初期化します。
QPlatform Input Contect Factory::create()の実現は以下の通りです。
QPlatformInputContext *QPlatformInputContextFactory::create()
{
    QPlatformInputContext *ic = 0;

    QString icString = QString::fromLatin1(qgetenv("QT_IM_MODULE"));    //       QT_IM_MODULE,              

    if (icString == QLatin1String("none"))
        return 0;

    ic = create(icString);    //      create         
    if (ic && ic->isValid())
        return ic;

    //          
    delete ic;
    ic = 0;

    QStringList k = keys();
    for (int i = 0; i < k.size(); ++i) {
        if (k.at(i) == icString)
            continue;
        ic = create(k.at(i));
        if (ic && ic->isValid())
            return ic;
        delete ic;
        ic = 0;
    }

    return 0;

}

QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key)
{
    QStringList paramList = key.split(QLatin1Char(':'));
    const QString platform = paramList.takeFirst().toLower();

#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
    if (QPlatformInputContext *ret = qLoadPlugin1(loader(), platform, paramList))    //   key(    )           (    QPlatformInputContext     )。
        return ret;
#endif
    return 0;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
付3:ヒントは何時ですか?
<1>
Qtには、ライブラリやプラグインのいくつかのクラスをロードできます。      QLibrary、    QPlugin Loader    QFactory Loader    QStatic Plugin(これはしばらく研究しない)     QLibraryとQPluginLoader依存の「私有データクラス」はいずれもQLibrary Privateであり、一つのQLibraryまたはQPlugin Loaderのオブジェクトは一つのQLibrary Privateオブジェクトがあり、一つのライブラリまたはプラグインに対応しています。QLibrary Privateタイプの要素は、一連のライブラリまたはプラグインに対応しています。したがって、QLibrary PrivateはQt中のライブラリまたはプラグインに関連するコアデータクラスであり、各ライブラリは一つのQLibrary Privateオブジェクトに対応しています。   <2>1.Qt AsistantでHow to Create Qt Pluginsを検索すると、ここではプラグインの作成方法を詳しく説明しています。主に高級API(Higher-level API)と低レベルAPI(Lower-level API)があります。2つのAPIはプラグインを書くために使用できます。高度なAPIの使用方法はQtのソースコードに多くの例が見られます。低レベルのAPIの使用例はシリーズの文章の最後に与えられます。2.プラグインが書かれていない場合、proファイルはQt Asistantでqmake Manualを検索できます。このページには多くのリンクがあります。Qmake Language.pro.pro.pro.pro.proファイルの構文、Varablesリンク講.proファイルの変数(QT、CONFIG、TEMPLATEなどの変数)、 Replace FunctionsとReplace Functionsはリンクしていくつかの内部建設の関数を言います。(proファイルで使用できます。)