【发布时间】:2020-07-09 22:20:54
【问题描述】:
我想从 QML/JS 调用一个 C++ 函数,该函数将在 QML 中实例化的 C++ 类(数据对象)作为参数。 程序编译并运行,但是当我尝试从 QML/JS 调用 C++ 函数时,出现以下错误:
“无法将参数 0 转换为” “onClicked@qrc:/main.qml:26” “将不兼容的参数从 JavaScript 传递给 C++ 函数是危险的并且已被弃用。” “这将在 Qt 的未来版本中引发 JavaScript TypeError!”
我已经尝试了引用/值/指针调用的所有组合,以及 Q_GADGET 和 Q_OBJECT 的多种变体,但我根本无法让它工作。
我使用基于 QObject 的 C++ 数据类型以及所有调用组合的最小示例如下:
C++ 数据类型
#include <QObject>
#include <QDebug>
//Data type which should be instantiated in QML
class CustomDataObject : public QObject{
Q_OBJECT
Q_PROPERTY(int exampleValue MEMBER exampleValue)
public:
int exampleValue;
explicit CustomDataObject(QObject * parent = nullptr) : QObject(parent) {}
~CustomDataObject() = default;
CustomDataObject(const CustomDataObject& blob) {}
};
Q_DECLARE_METATYPE(CustomDataObject);
具有要调用的函数的 C++ 类
//Class with function called from QML
class UniqueDataBackend : public QObject {
Q_OBJECT
public:
//Call with native data type (works)
Q_INVOKABLE void processNativeObject(int value) {
qDebug() << "C++: Nativ Value: " << value;
}
//Call by value (does not work)
Q_INVOKABLE void processDataObjectByValue(const CustomDataObject data) {
qDebug() << "C++: Data Object Value: " << data.exampleValue;
}
//Call by reference (does not work)
Q_INVOKABLE void processDataObjectByReference(const CustomDataObject & data) {
qDebug() << "C++: Data Object Value: " << data.exampleValue;
}
//Call by pointer (does not work)
Q_INVOKABLE void processDataObjectByPointer(const CustomDataObject * data) {
qDebug() << "C++: Data Object Value: " << data->exampleValue;
}
UniqueDataBackend(QObject * parent = nullptr) : QObject(parent) {}
~UniqueDataBackend() = default;
UniqueDataBackend(const UniqueDataBackend& blob) {}
};
Q_DECLARE_METATYPE(UniqueDataBackend);
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlEngine>
#include "CustomStruct.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
//Register types for use in QML
qRegisterMetaType<CustomDataObject>();
qmlRegisterType<CustomDataObject>("Custom.Types", 1, 0, "CustomDataObject");
//Register intances for use in QML
engine.rootContext()->setContextProperty("UniqueDataBackend", new UniqueDataBackend());
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
QML 文件 (main.qml)
import QtQuick 2.12
import QtQuick.Controls 2.12
import Custom.Types 1.0
ApplicationWindow {
id: window
width: 400
height: 300
visible: true
CustomDataObject {
id: customData
exampleValue: 84
}
Button {
text: "Click me!"
anchors.fill: parent
onClicked: {
console.log("QML: Calling c++ function with native data type!")
UniqueDataBackend.processNativeObject(42)
console.log("QML: Checking value of custom data type in javascript: " + customData.exampleValue)
console.log("QML: Calling c++ function by value with custom data type!")
UniqueDataBackend.processDataObjectByValue(customData)
console.log("QML: Calling c++ function by reference with custom data type!")
UniqueDataBackend.processDataObjectByReference(customData)
console.log("QML: Calling c++ function by pointer with custom data type!")
UniqueDataBackend.processDataObjectByPointer(customData)
}
}
}
输出
qml: QML: Calling c++ function with native data type!
C++: Nativ Value: 42
qml: QML: Checking value of custom data type in javascript: 84
qml: QML: Calling c++ function by value with custom data type!
"Could not convert argument 0 at"
"onClicked@qrc:/main.qml:26"
"Passing incompatible arguments to C++ functions from JavaScript is dangerous and deprecated."
"This will throw a JavaScript TypeError in future releases of Qt!"
C++: Data Object Value: 0
qml: QML: Calling c++ function by reference with custom data type!
"Could not convert argument 0 at"
"onClicked@qrc:/main.qml:29"
"Passing incompatible arguments to C++ functions from JavaScript is dangerous and deprecated."
"This will throw a JavaScript TypeError in future releases of Qt!"
C++: Data Object Value: -842150451
qml: QML: Calling c++ function by pointer with custom data type!
qrc:/main.qml:32: Error: Unknown method parameter type: const CustomDataObject*
我认为这是自定义数据类型的问题,因为我可以毫无问题地调用具有本机数据类型的函数,但对于我的生活,我无法弄清楚。
非常感谢您的帮助/cmets!
【问题讨论】:
-
非 const 指针呢?
-
有效!我不知道我是如何忽视这一点的。万分感谢!想要将其写为答案,以便我将其标记为已解决?