fc2ブログ

Qtでプラグインフォルダのパスの設定方法

Qtで作ったアプリケーションを動かすときに、Qtのランタイムがあるフォルダに対してパスを通すだけでは、
起動してくれないらしく、たとえば、次のような非常に簡単なプログラムをビルドした場合、

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // メインウィンドウクラス
    PluginAutoLoadTest w;
    w.show();

    return a.exec();
}


Qtのランタイムにパスを通した状態で実行すると、次のようなメッセージが出て起動に失敗してしまいます。

「Failed to load platform plugin "windows". Available platforms...」

snapshot_276_140721_213746.png

このような問題が出る場合、実行ファイルがあるフォルダにQtのランタイムからプラグイン系のファイルをコピー
すれば良いのですが、ランタイムフォルダにパスを通している場合は、いちいちファイルをコピーするのが
面倒なので、なんとかプラグインのファイルを指定できないかと調べていたところ、どうもコマンドライン引数
からプラグインフォルダを設定出来る仕様のようです。

コマンドライン引数に、たとえば

a.exe -platformpluginpath "C:\Qt\Qt5.1.0\5.1.0\msvc2012_32_opengl-bld\plugins"

このようなオプションを指定してやると、指定したフォルダからプラグインを読み込んでくれます。

ですが、毎回こんな長いパラメータを指定して起動するのも面倒なので、自動でプラグインフォルダを
探てプログラムを起動する処理を作ってみました。

#include "stdafx.h"
#include "PluginAutoLoadTest.h"
#include <QtWidgets/QApplication>

#include <vector>
#include <string>
#include <QString>

class ArgWithPlugin
{
public:
    ArgWithPlugin(int argc, char *argv[])
    {
        InitStdArgumentsCopy(argc, argv);

        if (!IsExistLocalCopy(argv))
            AddReferenceToSDK();
    }

    int& GetArgc(void)
    {
        return argc_ext;
    }

    char** GetArgv(void)
    {
        return &arg_ext[0];
    }

private:
    void InitStdArgumentsCopy(int argc, char *argv[])
    {
        argc_ext = argc;
        arg_ext.reserve(argc_ext);
        for (int i = 0; i < argc; ++i)
        {
            arg_ext.push_back(argv[i]);
        }
    }

    bool IsExistLocalCopy(char *argv[])
    {
        QString dir = GetStartupPath(argv);
        
        if (QFile(dir + "\\" "Qt5Core.dll").exists())
            return true;
        if (QFile(dir + "\\" "Qt5Cored.dll").exists())
            return true;

        return false;
    }

    QString GetStartupPath(char *argv[])
    {
        QString cmd = QString::fromLocal8Bit(argv[0]);
        QString d = QFileInfo(cmd).dir().path();
        return QDir::toNativeSeparators(d);
    }

    QString GetPluginDirFromEnv(void)
    {
        QString sdk_dir = GetEnvParam("QTDIR");
        if (sdk_dir.isEmpty())
            return QString("");

        return sdk_dir + QString("\\plugins");
    }

    QString GetEnvParam(QString name)
    {
        QStringList envs = QProcess::systemEnvironment();
        for (int i = 0; i < envs.size(); ++i)
        {
            const QString& s = envs[i];
            int split_pos = s.indexOf("=");
            if (split_pos == -1)
                continue;

            QString name = s.left(split_pos);
            QString param = s.mid(split_pos + 1);

            if (s.left(5) == name)
                return param;
        }

        return QString("");
    }

    void AddReferenceToSDK(void)
    {
        plugin_opt = "-platformpluginpath";
        plugin_path = GetPluginDirFromEnv().toLocal8Bit();

        if (!plugin_path.empty())
        {
            arg_ext.push_back(&plugin_opt[0]);
            arg_ext.push_back(&plugin_path[0]);
            argc_ext += 2;
        }
    }

private:
    int argc_ext;
    std::vector<char*> arg_ext;

    std::string plugin_opt;
    std::string plugin_path;
};

int main(int argc, char *argv[])
{
    ArgWithPlugin ax(argc, argv);
    QApplication a(ax.GetArgc(), ax.GetArgv());

    PluginAutoLoadTest w;
    w.show();

    return a.exec();
}


この処理は、実行ファイルと同じフォルダにQtのランタイムがコピーされている場合は、そのフォルダに
プラグインもコピーされていると仮定し、何も行いません。
そうでない場合は、環境変数にQTDIRが設定されている場合、そのフォルダ+"\plugins"というフォルダ
にプラグインがあるという前提でアプリケーションを実行します。

スポンサーサイト



コメントの投稿

非公開コメント

カレンダー
02 | 2024/03 | 04
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 - - - - - -
最新記事
カテゴリ
Qt (21)
SDL (2)
MFC (2)
検索フォーム
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
リンク
リンク(管理用)
FC2カウンター