I want to call a C++ function from QML/JS, which takes a C++ class (data object) instantiated in QML as argument. The program compiles and runs, however when I try to call the C++ function from QML/JS I get the following error:
"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!"
I have tried all combination of call by reference/value/pointer, as well as multiple variations with Q_GADGET and Q_OBJECT but I simply cannot get it to work.
My minimum Example with QObject based C++ data type as well as all the call combinations is as follows:
C++ data type
#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 to call
//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 File (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)
}
}
}
Output
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*
I assume that it is a problem with custom data type as I can call a function with native data types without a problem, but for the life of me I cannot figure it out.
Thank you very much for your help/comments!