Вызов функции C ++ из QML / JS с объектом C ++ в качестве аргумента - PullRequest
0 голосов
/ 29 марта 2020

Я хочу вызвать функцию C ++ из QML / JS, которая принимает класс C ++ (объект данных), созданный в QML в качестве аргумента. Программа компилируется и запускается, однако, когда я пытаюсь вызвать функцию C ++ из QML / JS, я получаю следующую ошибку:

"Не удалось преобразовать аргумент 0 в" "onClicked@qrc: / main.qml : 26 "" Передача несовместимых аргументов в функции C ++ из JavaScript опасна и не рекомендуется. " «Это вызовет JavaScript TypeError в будущих выпусках Qt!»

Я перепробовал все комбинации вызова по ссылке / значению / указателю, а также несколько вариантов с Q_GADGET и Q_OBJECT, но я просто не могу получить это работает.

Мой минимальный пример с типом данных C ++ на основе QObject, а также всеми комбинациями вызовов выглядит следующим образом:

Тип данных 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*

Я предполагаю, что это проблема с пользовательским типом данных, так как я могу вызвать функцию с родными типами данных без проблем, но для жизни я не могу понять это.

Большое спасибо за вашу помощь / комментарии!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...