使用 CMake 创建 QML 插件
Create QML plugin with CMake
我正在尝试使用 CMake 创建简单的 QML C++ 插件。有我的消息来源:
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12)
project(qmltest LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# Path to installed Qt 5.15
set(Qt5Core_DIR ".../Qt/5.15.0/gcc_64/lib/cmake/Qt5Core")
set(Qt5Qml_DIR ".../Qt/5.15.0/gcc_64/lib/cmake/Qt5Qml")
set(Qt5Quick_DIR ".../Qt/5.15.0/gcc_64/lib/cmake/Qt5Quick")
find_package(Qt5 COMPONENTS Core Quick Qml REQUIRED)
LINK_DIRECTORIES(.../Qt/5.15.0/gcc_64/lib)
INCLUDE_DIRECTORIES(.../Qt/5.15.0/gcc_64/include)
INCLUDE_DIRECTORIES(.../Qt/5.15.0/gcc_64/include/QtQml)
set(QML_IMPORT_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "" FORCE)
add_library(dummy SHARED
"dummy.h" "dummy.cpp" "myplugin.h" "myplugin.cpp"
)
target_link_libraries(dummy Qt5::Core Qt5::Quick Qt5::Qml)
add_executable(${PROJECT_NAME} "main.cpp" "qml.qrc")
target_link_libraries(${PROJECT_NAME} dummy Qt5::Core Qt5::Quick Qt5::Qml)
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include <QtPlugin>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
dummy.h:
#ifndef DUMMY_H
#define DUMMY_H
#include <QObject>
class Dummy : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
explicit Dummy(QObject *parent = nullptr);
QString name();
void setName(const QString x);
signals:
void nameChanged();
public slots:
private:
QString _name;
};
#endif // DUMMY_H
myplugin.h:
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QtQml/QQmlEngineExtensionPlugin>
#include <QObject>
#include <QQmlApplicationEngine>
#include <iostream>
#include <dummy.h>
class MyPlugin : public QQmlEngineExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
public:
void registerTypes(const char* uri) {
std::cout << "GGGGGGGGGGGGGGGG\n";
qmlRegisterType<Dummy>(uri, 1, 0, "Dummy");
qmlRegisterModule(uri, 1, 0);
qmlProtectModule(uri, 1);
}
};
#endif // MYPLUGIN_H
main.qml:
import MyPlugin 1.0
Window {
Dummy {}
}
我还在我的构建目录中创建了名为 MyPlugin 的目录,其中 link 用于构建 libdummy.so 和 qmldir 文件,如下所示:
module MyPlugin
plugin dummy
项目构建,但是当我 运行 它时,我得到一个错误:
plugin cannot be loaded for module "MyPlugin": Cannot protect module MyPlugin 1 as it was never registered
我的 registerTypes
函数的调试输出尚未被调用(stdout 上没有输出),因此我假设由于某些原因尚未注册类型。如果我通过将此行添加到 myplugin.cpp:
来尝试静态注册类型
static int unused = qmlRegisterType<Dummy>("MyPlugin", 1, 0, "Dummy");
,我得到一个错误:
plugin cannot be loaded for module "MyPlugin": Namespace 'MyPlugin' has already been used for type registration
这个插件有什么问题以及如何让它与 CMake 一起工作?
Qt 包含 2 个不同的 qml 插件基础 class:
QQmlEngineExtensionPlugin(这个 class 是在 Qt 5.14 中引入的)和
QQmlExtensionPlugin
myplugin.h:
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QtQml/QQmlExtensionPlugin>
#include "dummy.h"
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
public:
void registerTypes(const char* uri) {
qmlRegisterType<Dummy>(uri, 1, 0, "Dummy");
}
};
#endif // MYPLUGIN_H
我正在尝试使用 CMake 创建简单的 QML C++ 插件。有我的消息来源:
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12)
project(qmltest LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# Path to installed Qt 5.15
set(Qt5Core_DIR ".../Qt/5.15.0/gcc_64/lib/cmake/Qt5Core")
set(Qt5Qml_DIR ".../Qt/5.15.0/gcc_64/lib/cmake/Qt5Qml")
set(Qt5Quick_DIR ".../Qt/5.15.0/gcc_64/lib/cmake/Qt5Quick")
find_package(Qt5 COMPONENTS Core Quick Qml REQUIRED)
LINK_DIRECTORIES(.../Qt/5.15.0/gcc_64/lib)
INCLUDE_DIRECTORIES(.../Qt/5.15.0/gcc_64/include)
INCLUDE_DIRECTORIES(.../Qt/5.15.0/gcc_64/include/QtQml)
set(QML_IMPORT_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "" FORCE)
add_library(dummy SHARED
"dummy.h" "dummy.cpp" "myplugin.h" "myplugin.cpp"
)
target_link_libraries(dummy Qt5::Core Qt5::Quick Qt5::Qml)
add_executable(${PROJECT_NAME} "main.cpp" "qml.qrc")
target_link_libraries(${PROJECT_NAME} dummy Qt5::Core Qt5::Quick Qt5::Qml)
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include <QtPlugin>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
dummy.h:
#ifndef DUMMY_H
#define DUMMY_H
#include <QObject>
class Dummy : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
explicit Dummy(QObject *parent = nullptr);
QString name();
void setName(const QString x);
signals:
void nameChanged();
public slots:
private:
QString _name;
};
#endif // DUMMY_H
myplugin.h:
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QtQml/QQmlEngineExtensionPlugin>
#include <QObject>
#include <QQmlApplicationEngine>
#include <iostream>
#include <dummy.h>
class MyPlugin : public QQmlEngineExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
public:
void registerTypes(const char* uri) {
std::cout << "GGGGGGGGGGGGGGGG\n";
qmlRegisterType<Dummy>(uri, 1, 0, "Dummy");
qmlRegisterModule(uri, 1, 0);
qmlProtectModule(uri, 1);
}
};
#endif // MYPLUGIN_H
main.qml:
import MyPlugin 1.0
Window {
Dummy {}
}
我还在我的构建目录中创建了名为 MyPlugin 的目录,其中 link 用于构建 libdummy.so 和 qmldir 文件,如下所示:
module MyPlugin
plugin dummy
项目构建,但是当我 运行 它时,我得到一个错误:
plugin cannot be loaded for module "MyPlugin": Cannot protect module MyPlugin 1 as it was never registered
我的 registerTypes
函数的调试输出尚未被调用(stdout 上没有输出),因此我假设由于某些原因尚未注册类型。如果我通过将此行添加到 myplugin.cpp:
static int unused = qmlRegisterType<Dummy>("MyPlugin", 1, 0, "Dummy");
,我得到一个错误:
plugin cannot be loaded for module "MyPlugin": Namespace 'MyPlugin' has already been used for type registration
这个插件有什么问题以及如何让它与 CMake 一起工作?
Qt 包含 2 个不同的 qml 插件基础 class: QQmlEngineExtensionPlugin(这个 class 是在 Qt 5.14 中引入的)和 QQmlExtensionPlugin
myplugin.h:
#ifndef MYPLUGIN_H
#define MYPLUGIN_H
#include <QtQml/QQmlExtensionPlugin>
#include "dummy.h"
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
public:
void registerTypes(const char* uri) {
qmlRegisterType<Dummy>(uri, 1, 0, "Dummy");
}
};
#endif // MYPLUGIN_H