Qt の C++ から QML の function を実行する方法
QML 内に記述された JavaScript の function を C++ から呼び出してみたいと思ったことはありませんか?ありませんか?
というわけで(以前に試してみてたしかダメだったのですが、Qt 5.2 から JavaScript の実行エンジンが変わったことによって、ひょっとして今ならできるかも?と思って再度)試してみました。
exec-function-in-qml-from-cpp.pro
TEMPLATE = app TARGET = exec-function-in-qml-from-cpp QT = qml SOURCES = main.cpp RESOURCES = main.qrc
シンプルなコンソールアプリで QML の実験をするための最小構成になっています。
main.qml
import QtQml 2.2 QtObject { id: root function echo(msg) { console.debug(msg) return msg } }
これが今回使用する QML ファイルで、この echo 関数を C++ から実行します。
main.qrc
<RCC> <qresource prefix="/"> <file>main.qml</file> </qresource> </RCC>
QML ファイルをリソースに埋め込みます。
main.cpp
#include <QtQml> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QQmlEngine engine; QQmlComponent component(&engine); component.loadUrl(QUrl("qrc:/main.qml")); QObject *object = component.create(); { const QMetaObject *metaObject = object->metaObject(); for (int i = object->staticMetaObject.methodCount(); i < metaObject->methodCount(); i++) { qDebug() << i << metaObject->method(i).name(); QVariant ret; qDebug() << metaObject->method(i).invoke(object, Qt::DirectConnection, Q_RETURN_ARG(QVariant, ret), Q_ARG(QVariant, QStringLiteral("test"))); qDebug() << ret; } } delete object; QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); return app.exec(); }
QQmlEngine を使用して main.qml を実行します。
作成した main.qml のオブジェクトのメタオブジェクトから main.qml 内で作成された function を取得し、実行結果をデバッグ出力しています。
実行
$ qmake $ make $ ./exec-function-in-qml-from-cpp 5 "echo" qml: test true QVariant(QString, "test")
というわけで、C++ から QML で定義した関数を呼べることがわかりました。QVariant で返値と引数を渡してあげるのがポイントですね。