Qt World Summit: Register Today!

Dynamically call methods from a scripting engine using QMetaMethod and QVariant.

  • Hi, I'm wrinting a python api for one of my app using pybind11 (which is the best choice for me, even if it is sometimes not easy to integrate it with some Qt paradigms).

    I want to let the programmer using my api to interact with a certain family of qobjects (the editable items) using the meta object system through python.

    For the properties it's easy. I just had to wrote a method to convert pybind11::handle to QVariant, treating the cases that matter for my software (strings, numbers and nested editable items) and vice versa.

    But for some use cases I need invokable methods (for examples creating a new nested editable item and getting back its attributed id). I found this thread that describe how we can cheat with QGenericReturnArgument, QGenericArgument and QVariant to invoke a method once we know its signature, have the corresponding QVariants converted from the corresponding pybind11::handle (provided in a tuple): Qt invoke method with QVariant.

    So I can write something like that:

    pybind11::object EditableItemWrapper::invokeMethod(std::string m_name, py::tuple args) {
         QMetaMethod m = getMeth(m_name); //simplified
         do_checks(); //see if arguments matches both in numbers and types.
         int narg = m.parameterCount();
         switch(narg) {
         case 0:
               //do the business here.
               void v = NULL;
               const char* name = QMetaType::type(QMetaType(m.returnType()).metaObject().className());
               QVariant retVal (m.returnType(), v);
               bool sucess = invokeMethod(wrapped_obj(), m_name.c_str(), QGenericReturnArgument(name, retVal.data());
         case n:
               //repeat cleverly for each n up to a reasonable maximal under Q_METAMETHOD_INVOKE_MAX_ARGS
               //use the same tric for input values, creating the appropritate QVariant and giving the data() ptr to QGenericArgument

    But, the doc says its discouraged to work like that... Why ? (For example there is this limitation on the number of parameters, but it's a needed evil, isn't it ?)

    Ideally I'd like to invoke my method given a name, A QVariantList as parameter and get back a QVariant and a status code as return, isn't there something to do it already ?

    And is there any other solution ? What do you think ?

    Thanks in advance for your answers.


Log in to reply