Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to translate a function name in QJsonObject from string to function pointer?



  • I have a QJsonObject containing:

    decoder: "decoderFn"
    

    To extract the function name as a string:

    QJsonObject::iterator itrDecoder = objDecoder.find(clsJSON::mscszDecoder);
    
    if ( itrDecoder == objDecoder.end() ) {
        continue;
    }
    QString strDecoder = itrDecoder.value().toString();
    

    Can I translate strDecoder to a function pointer or do I need to change the string contents to a full prototype of the function?

    And use eval? Will try out whilst waiting for a comment / answer...


  • Moderators

    If your target object is a QObject, and your method is marked as slot or Q_INVOKABLE, you can call that method by name (taken from JSON) using invokeMethod().



  • @sierdzio , thank you, can you show an example? My functions in the JSON aren't part of a class, something like:

    bool blnDecodeHeartbeat(const QJsonObject& crobjJSON) {
        clsModule* pModule = pDecodeModuleAndPort(crobjJSON);
        if ( pModule != nullptr ) {
            if ( pModule->blnIsMsgSndrSet() != true ) {
                QJsonObject::const_iterator citrFound = crobjJSON.find(clsJSON::mscszPort);
    
                if ( citrFound == crobjJSON.end() ) {
        //No port in message, cannot set port, abort decode!
                    return false;
                }
            }            
            pModule->updateHearbeat();
        //Extract the message type from the message
            clsJSON::sendAck(crobjJSON);
            return true;
        }
        return false;
    }
    

    If wrapping them up in a class would help, I can do that...can you help with an example? All the functions I want to use like this will have the same prototype, I mean same return and parameters.


  • Moderators

    Hm in that case I'd rather do an if-else cascade and call proper function depending on JSON data.

    Anyway, coming back to invokeMethod() idea:

    class MyClass : public QObject
    {
      Q_OBJECT
    
    public:
      Q_INVOKABLE int decoderFn(int something);
    };
    
    // And now, in your JSON parser:
    MyClass myObject = ...;
    QString strDecoder = itrDecoder.value().toString();
    int returnValue = 0;
    bool isOk = QMetaObject()::invokeMethod(
      myObject, strDecoder.constData(),
      Qt::DirectConnection,
      Q_RETURN_ARG(int, returnValue), Q_ARG(int, 123));
    
    qDebug() << "Result is:" << returnValue << "is ok?" << isOk;
    


  • @sierdzio , I was trying:

            QMetaObject::invokeMethod(nullptr, cpszDecode, Qt::DirectConnection
                                     ,Q_RETURN_ARG(bool, blnRet)
                                     ,Q_ARG(const QJsonObject&, "crobjJSON"));
    

    With the first parameter to see if it would work but I get:

    no matching constructor for invalidation of 'QArgument<const QJsonObject&>'
    

    If I move my decode functions into a class and pass the type to the first parameter how do I satisfy the argument type?



  • @SPlatten said in How to translate a function name in QJsonObject from string to function pointer?:

    no matching constructor for invalidation of 'QArgument<const QJsonObject&>'

    First, "crobjJSON" is a string not a QJsonObject!

    Second, Q_ARG() should be something like Q_ARG(QJsonObject, const &crobjJSON)


  • Moderators

    Object is needed, I don't think it will work with nullptr. Argument - try with just QJsonObject, without const reference. If that still fails, maybe you need to register QJsonObject with with meta object system.

    Or use if-else as mentioned.



  • @KroMignon I was using the example:

    QString retVal;
    QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
                              Q_RETURN_ARG(QString, retVal),
                              Q_ARG(QString, "sqrt"),
                              Q_ARG(int, 42),
                              Q_ARG(double, 9.7));
    

    on:
    https://doc.qt.io/qt-5/qmetaobject.html#invokeMethod

    Which is why I thought the second parameter of Q_ARG had to be a string.


Log in to reply