12,925
回編集
218行目: | 218行目: | ||
# 実行ファイル側のQMLファイルから動的ライブラリのオブジェクトのメソッドを呼び出して、動的ライブラリ内のQMLファイルを表示する。 | # 実行ファイル側のQMLファイルから動的ライブラリのオブジェクトのメソッドを呼び出して、動的ライブラリ内のQMLファイルを表示する。 | ||
<br> | <br> | ||
上記セクションにある動的ライブラリの変更点のみを、以下に示す。<br> | |||
<br> | <br> | ||
まず、動的ライブラリのクラスおよびメソッドの変更点を記述する。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
// | // LibSample.h (動的ライブラリ側) | ||
#ifndef | #ifndef LIBSAMPLE_H | ||
#define | #define LIBSAMPLE_H | ||
#include < | #include <QObject> | ||
#include <QString> | |||
#include <QQmlComponent> | |||
#include <QtQml/qqmlengine.h> | |||
#include "LibSample_global.h" | |||
class LIBSAMPLE_EXPORT LibSample : public QObject | |||
{ | |||
Q_OBJECT | |||
#endif // | public: | ||
explicit LibSample(QQmlEngine *engine, QObject *parent = nullptr); | |||
Q_INVOKABLE void showQmlWindow(); | |||
private: | |||
QQmlEngine *m_engine; | |||
}; | |||
extern "C" { | |||
LibSample* createLibSample(); | |||
void destroyLibSample(LibSample *instance); | |||
} | |||
#endif // LIBSAMPLE_H | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
// | // LibSample.cpp (動的ライブラリ側) | ||
#include " | #include <QQmlComponent> | ||
#include <QtQuick/QQuickWindow> | |||
#include "LibSample.h" | |||
LibSample::LibSample(QQmlEngine *engine, QObject *parent) : QObject(parent), m_engine(engine) | |||
{ | |||
qDebug() << "LibSample lib"; | |||
} | |||
void LibSample::showQmlWindow() | |||
{ | { | ||
QQmlComponent component(m_engine, "qrc:/Hoge/Hoge.qml"); | |||
{ | |||
QObject *object = component.create(); | |||
if (object) { | |||
QQuickWindow *window = qobject_cast<QQuickWindow*>(object); | |||
if (window) { | |||
window->show(); | |||
} | |||
} | } | ||
} | |||
LibSample* createLibSample() | |||
{ | |||
return new LibSample(); | |||
} | |||
void destroyLibSample(LibSample *instance) | |||
{ | |||
delete instance; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
次に、実行ファイル側 (動的ライブラリを使用する側) から動的ライブラリを読み込み、動的ライブラリのクラスのインスタンスを生成する。<br> | |||
生成したインスタンスをQMLコンテキストにセットして、QMLファイルから動的ライブラリのクラスのメソッドを呼び出す。<br> | |||
<br> | <br> | ||
<code>QLibrary</code>クラスから呼び出す関数は、必ず、C言語のグローバル関数として定義すること。<br> | <code>QLibrary</code>クラスから呼び出す関数は、必ず、C言語のグローバル関数として定義すること。<br> | ||
272行目: | 296行目: | ||
<br> | <br> | ||
<u>※注意</u><br> | <u>※注意</u><br> | ||
<u> | <u>Windowsでは、動的ライブラリからメソッドを呼び出すには、<code>__declspec(dllexport)</code>を関数の前に付加すること。</u><br> | ||
<br> | <br> | ||
<code>QLibrary</code>クラスのコンストラクタには、<code>.so</code>拡張子または<code>.dll</code>拡張子を付加しないライブラリ名を渡す。<br> | <code>QLibrary</code>クラスのコンストラクタには、<code>.so</code>拡張子または<code>.dll</code>拡張子を付加しないライブラリ名を渡す。<br> | ||
動的ライブラリをリンクするには、<code>load</code>メソッドを実行する。<br> | 動的ライブラリをリンクするには、<code>load</code>メソッドを実行する。<br> | ||
<br> | |||
次に、<code>resolve</code>メソッドを使用して呼び出す関数名を渡して、関数が存在する場合は関数ポインタが返る。<br> | 次に、<code>resolve</code>メソッドを使用して呼び出す関数名を渡して、関数が存在する場合は関数ポインタが返る。<br> | ||
メソッド名や型が間違っている場合は、<code>0</code>が返る。<br> | |||
<br> | <br> | ||
もし、メソッド内でグローバル変数の値が変更された場合、次の関数を呼び出した時でも、グローバル変数の値を保持し続ける。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
// main.cpp | // main.cpp (実行ファイル側) | ||
#include < | #include <QGuiApplication> | ||
#include <QQmlApplicationEngine> | |||
#include <QQmlContext> | |||
#include <QLibrary> | #include <QLibrary> | ||
#include "LibSample.h" | |||
using | |||
using CreateLibSampleInstance = LibSample* (*)(); | |||
using DestroyLibSampleInstance = void (*)(LibSample*); | |||
int main(int argc, char * argv[]) | int main(int argc, char *argv[]) | ||
{ | { | ||
QGuiApplication app(argc, argv); | |||
QQmlApplicationEngine engine; | |||
const QUrl url(u"qrc:/main.qml"_qs); | |||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, | |||
[url](QObject *obj, const QUrl &objUrl) { | |||
if (!obj && url == objUrl) | |||
QCoreApplication::exit(-1); | |||
}, Qt::QueuedConnection); | |||
engine.load(url); | |||
QLibrary lib("LibSample"); | |||
QLibrary lib(" | if (lib.load()) { | ||
lib.load(); | CreateLibSampleInstance createInstance = (CreateLibSampleInstance) lib.resolve("createLibSample"); | ||
DestroyLibSampleInstance destroyInstance = (DestroyLibSampleInstance) lib.resolve("destroyLibSample"); | |||
if (createInstance && destroyInstance) { | |||
LibSample *sample = createInstance(); | |||
engine.rootContext()->setContextProperty("libSample", sample); | |||
QObject::connect(&app, &QCoreApplication::aboutToQuit, [sample, destroyInstance]() { | |||
{ | destroyInstance(sample); | ||
}); | |||
} | |||
else { | |||
qWarning() << "インスタンスメソッドの作成 / 破棄の解決に失敗"; | |||
} | |||
} | |||
else { | |||
qWarning() << "動的ライブラリの読み込みに失敗"; | |||
} | } | ||
return | return app.exec(); | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |