从 C++ 加载 QML 插件
QML Plugin load from C++
是否可以从 C++ 加载 QML 插件,比如说,从 QPluginLoader
来使用它的功能?在我的项目中,我有一个带有版本信息的 qml 插件,我想从 C++ 读取它。
示例:
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();
}
答案是.. 是。几个月后,我能够再次完成这项任务。
所以,在qt源码中我们可以看到什么QQmlExtensionPlugin
。真的是一个qt插件(我们可以通过QPluginLoader
打开)-QPlugin
。我认为它应该列在 Qt's plugin type list.
为了能够在应用程序中打开您的 qml 插件,您的插件 class 必须实现一些您将在应用程序中使用 qobject_cast
转换到的接口。在我的项目中它看起来像:
#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
接下来,在打开插件的应用main.cpp中:
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";
}
这里最糟糕的是,您必须提供插件(共享库)的完整路径,并且您需要知道它在不同系统上的安装位置。
是否可以从 C++ 加载 QML 插件,比如说,从 QPluginLoader
来使用它的功能?在我的项目中,我有一个带有版本信息的 qml 插件,我想从 C++ 读取它。
示例:
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();
}
答案是.. 是。几个月后,我能够再次完成这项任务。
所以,在qt源码中我们可以看到什么QQmlExtensionPlugin
。真的是一个qt插件(我们可以通过QPluginLoader
打开)-QPlugin
。我认为它应该列在 Qt's plugin type list.
为了能够在应用程序中打开您的 qml 插件,您的插件 class 必须实现一些您将在应用程序中使用 qobject_cast
转换到的接口。在我的项目中它看起来像:
#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
接下来,在打开插件的应用main.cpp中:
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";
}
这里最糟糕的是,您必须提供插件(共享库)的完整路径,并且您需要知道它在不同系统上的安装位置。