Q_DECLARE_METATYPE ... C struct straight to QML?



  • Hi,

    I have been intrigued by the intent of the macro Q_DECLARE_METATYPE. I would like to use it to take some legacy code C structs and use them directly in QML. I can get as far as getting the variant to QML, but I can't extract the individual values of the struct. QML recognizes at least the name of the struct, but I can't figure out how to cast the QVariant back into the struct on the QML side. The only way seems to be to have a C++ proxy class that turns the structs into QVariantMaps, and then everything works just fine. I'm trying to find a much more lazy approach, given the size of the legacy code base in C.

    Here is a small struct example. The comments in the code show what I'm thinking in terms of meeting the requirements for using Q_DECLARE_METATYPE, and where the code falls short.

    C++ Main function and declaration of the struct:

    @

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QString>
    #include <QDebug>
    #include <QQmlContext>
    #include <QMetaType>
    #include <QtQml>
    #include <QObject>

    struct MyStruct
    {
    // Q_OBJECT - don't even think about it. MOC throws a fit.
    int one;
    QString two;
    };
    Q_DECLARE_METATYPE(MyStruct)

    int main(int argc, char *argv[])
    {

    QGuiApplication app(argc, argv);
    int metaTypeId = 0;
    
    MyStruct* pEmpty = new MyStruct;          // Cpp provides default constructor.
    qDebug()<< "Empty One: " << pEmpty->one;  // Cpp CAN extract the elements of
    qDebug()<< "Empty Two: " << pEmpty->two;  // the default constructor.
    
    delete (pEmpty);                           // default destructor is provided.
    // qDebug()<< "Deleted Two: " << pEmpty->two;  // Causes exception as expected
    
    MyStruct s={1, "two"};                    // Cpp provides a default copy constructor
    QVariant var;
    var.setValue(s);
    MyStruct t=var.value<MyStruct>();         // Cpp provides method make a struct from a QVariant
    qDebug()<< "C++ One: " << t.one;          // Cpp CAN extract the elements of the struct after being a QVariant.
    qDebug()<< "C++ Two: " << t.two;          // but must be recast to a struct.
    
    metaTypeId = qRegisterMetaType<MyStruct>("MyStruct");
    qDebug() << "My registered ID: " <&lt; metaTypeId;
    // CAN register the struct as a metatype.
    
    // canNOT register the struct as a QML type (probably because it is not a Q_OBJECT)
    // qmlRegisterType&lt;MyStruct>("TMyStruct", 1, 0, "TMyStruct");
    
    QQmlApplicationEngine engine;
    QQmlContext* ctxt = engine.rootContext();
    ctxt->setContextProperty("structObject", var);
    // CAN reference the instance of the variant of the struct in QML
    
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
    

    }
    @

    QML File

    @
    import QtQuick 2.3
    import QtQuick.Window 2.2

    Window {
    Component.onCompleted: {
    console.log("A StructObject is:", structObject);
    console.log("Has type: ", typeof(structObject));
    console.log("Has string: ", structObject.toString());
    console.log("Has int value: ", structObject.one);
    console.log("Has string value: ", structObject.two);
    console.log("Has length: ", structObject.length);
    Qt.quit();
    }
    }
    @

    Results:

    @
    QML debugging is enabled. Only use this in a safe environment.
    Empty One: -1232878432
    Empty Two: ""
    C++ One: 1
    C++ Two: "two"
    My registered ID: 1027
    OpenGL Warning: Failed to connect to host. Make sure 3D acceleration is enabled for this VM.
    qml: A StructObject is: QVariant(MyStruct)
    qml: Has type: object
    qml: Has string: QVariant(MyStruct)
    qml: Has int value: undefined
    qml: Has string value: undefined
    qml: Has length: undefined
    @

    Thanks in advance for the help.

    Brian


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.