Reputation: 16695
Is it possible to load QML plugin from C++, say, from QPluginLoader
to work with it's functions? In my project, I have a qml plugin with a version information in it and I want to read it from C++.
Example:
main() {
// ...
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///ui/views/mainwindow.qml")));
if (parser.isSet(verionsOption)) {
QSharedPointer<QQmlExtensionPlugin> myPlugin = // load plugin
std::cout << "Version of plugin: " << myPlugin->version() << std::endl;
}
return app.exec();
}
Upvotes: 7
Views: 2904
Reputation: 16695
The anwser is.. yes. After few months I was able to get to this task back again.
So, in the qt source code we can see what QQmlExtensionPlugin
. It is really a qt plugin (which we are able to open through QPluginLoader
) - QPlugin
. In my opinion it should be listed in Qt's plugin type list.
To be able to open your qml plugin in the application your plugin class must implement some interface to which you will cast with qobject_cast
in the application. In my project it looks like:
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QQmlExtensionPlugin>
class ExternalInterface
{
public:
virtual const QString pluginVersion() const = 0;
virtual const QString qxmppVersion() const = 0;
virtual ~ExternalInterface() {}
};
Q_DECLARE_INTERFACE(ExternalInterface, "com.my.ExternalInterface")
class MyPlugin : public QQmlExtensionPlugin, public ExternalInterface
{
Q_OBJECT
Q_INTERFACES(ExternalInterface)
Q_PLUGIN_METADATA(IID "com.MyPlugin")
public:
void registerTypes(const char *uri);
void initializeEngine(QQmlEngine *engine, const char *uri);
const QString pluginVersion() const final override;
const QString qxmppVersion() const final override;
};
#endif // MYPLUGIN_H
Next, in main.cpp of the application which opens the plugin:
ExternalInterface* pluginVersion = nullptr;
#ifdef Q_OS_MACOS
const QString fileSuffix = ".dylib";
#else
const QString fileSuffix = ".so";
#endif
QPluginLoader qmlPlugin(QApplication::applicationDirPath() + "../PlugIns/quick/libmyplugin" + fileSuffix);
qmlPlugin.load();
if (qmlPlugin.isLoaded()) {
pluginVersion = qobject_cast<ExternalInterface*>(qmlPlugin.instance());
} else {
qmlPlugin.setFileName(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath) + "/fx/my/libmyplugin" + fileSuffix);
qmlPlugin.unload();
qmlPlugin.load();
if (qmlPlugin.isLoaded()) {
pluginVersion = qobject_cast<ExternalInterface*>(qmlPlugin.instance());
} else {
qDebug() << "ERROR while opening plugin: " << qmlPlugin.errorString();
}
}
if (pluginVersion) {
qDebug() << "Plugin: \n" << pluginVersion->pluginVersion() << "\n"
<< pluginVersion->qxmppVersion() << "\n"
<< "Location: " << qmlPlugin.fileName();
} else {
qDebug() << "Can't obtain version information from the plugin";
}
The worst thing here is that you must provide full path to the plugin (shared library) and you need to know where it installs on different systems.
Upvotes: 6