Search code examples
javascriptqt5qjsengine

Custom C++ type to QJSEngine: member function return value is always QVariant


I have a set of C++ classes exposed to javascript in Qt 5, based on the QJSEngine (because Qt script seems to be deprecated).

My QObject-derived classes A and B have the Q_OBJECT macro and use the Q_DECLARE_METATYPE macro as well.

I have exposed factory functions for my classes that allow me to create new instances from inside javascript. All the following works fine:

a = namespace.createNewA(); // QJSEngine reports a type A object
b = namespace.createNewB(); // QJSEngine reports a type B object
b.SetParent(a); // SetParent is a slot of B taking a const A& parameter, gets called correctly
// But now.
b.GetParent(); // Reports QVariant(A), even though this is a slot: A GetParent() const

Is there a way for me to ensure that GetParent in javascript gets recognized as an actual type A object, instead of a QVariant?


Solution

  • I figured out the issues with my original code:

    1. Using Qt slots with return values is probably not a good idea in the general case (see e.g. Qt: meaning of slot return value?). I changed the function to Q_INVOKABLE, which didn't actually change the result but it seemed a safer place to continue from.
    2. Returning by value doesn't seem to be a good idea for the scripting/wrapping either. Digging through the code with a debugger I found that the QVariant cast-to-qobject failed, and that made a lightbulb go off: by-value probably breaks the qobject_cast that tries to look up the QObject-derived type. I changed the call to return a pointer-to-QObject and now the QJSEngine reports the object as the correct type.

    This required some changes to my code setup, because the returned value used to be a temporary, but I can live with that.