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

QRemoteObject Dynamic Replica unable to call slot with return value



  • Re: [Qt Remote Objects]

    Hello QT folks,
    I get the same problem as the "one year old" post above:
    It seems that InvokeMethod on Replica doesn't support return value.
    I have a code like this which works perfectly on Host side, but not on Replica Side.

        QString retVal;
        bool success = QMetaObject::invokeMethod(_replica,"getName", Qt::DirectConnection,
            Q_RETURN_ARG(QString, retVal),
            Q_ARG(QString, "id")
         );
    

    I have only succeeded in calling void returning slots and even in this case, in DirectConnection mode, the invokeMethod finished before host slot invocation, so it seems that no host answer is in waiting.

    If i understand well the topic of REPC (i haven't try it yet), it seems that the calling of returning value slots is possible:
    Usage is to declare SLOT followed by the desired signature wrapped in parentheses. The return value can be included in the declaration. If the return value is skipped, void will be used in the generated files.

    Do REPC do some kind of magic to allow this feature, or did miss something ?

    Thanks for help.



  • After digging in REPC generated code and RO sources, i know now there is really some "kind of magic" in the REPC code.
    The call of returning value slot in REPC generated object use the protected sendWithReply function which is an async call, returning a kind of future object: QRemoteObjectPendingReply<T>.
    Ok nice. The problem is that the QRemoteObjectDynamicReplica have no public constructor, so no way to use this function even by derivation.
    The slot signature in the replica metaobject also has no functor parameter to get the return value async. So how?

    If there is no way (without re-coding a large part) to do this, I find this lack of feature really troublesome in my case, where the main spec is to have no use of REPC.
    I hope i missed something because it call really my choice of QTRemote into question after quite a lot of work :(

    A subsidiary question could be : Why is the QRemoteObjectDynamicReplica(QRemoteObjectNode *node, const QString &name) constructor private ?
    If public, it would allow to overload acquireDynamic in QRemoteObjectNode and extend QRemoteObjectDynamicReplica by derivation, for, in this case, expose internally the sendAndReply function.
    I understand principle of encapsulation but not when dead-end.

    If someone had a clue, i'll take it gratefully.


  • Moderators

    Hi @daes

    since QRemoteObject is a rather new class in Qt, the use rather specific and no-one could answered your original query (yet), even after a couple of days, I think this issue may be something that is unlikely de be answered by other users.

    I would suggest taking this to the mailing List
    The developers are much more active over there than here in the user forum. So getting into contact with someone more knowledgeable about QRemoteObjects is much more likely there 😁



  • @j-hilk
    Hi j-hilk and thanks for information.
    I don't think the use case is so specific on QtRemote, it is feature in Static usage. It is just either not allowed in Dynamic or perhaps (hope) only not well documented :)
    Thanks however for your advice, i will try to get more information about that on mailing list.



  • Hi,
    For those who are looking for an answer on this, there is a way :) : the QRemoteObjectPendingCall undocumented argument.
    ( Thanks again to j-hilk for the mailing list, i get the info in a day)

    QString retVal;
        bool success = QMetaObject::invokeMethod(_replica,"getName",Qt::DirectConnection,
            Q_RETURN_ARG(QRemoteObjectPendingCall, call),
            Q_ARG(QString, "id")
         );
    
    auto e = call.error();// , QRemoteObjectPendingCall::InvalidMessage);
    	
    	call.waitForFinished();
    	
    	//QVERIFY(call.isFinished());
    	//QCOMPARE(call.returnValue().type(), QVariant::String);
    	qDebug() << QMetaType::typeName(call.returnValue().type());
    	
    	QString retVal = call.returnValue().toString();
    

    This is exactly the same kind a future object available for REPC Replica (except not templated)
    No Documentation but there is some example in :
    Qt Remote Objects integration tests
    And it work great

    I asked a second question about the exposition of this pending value in QML and will post here too if i get some answer about that.



  • Ok i get the answer from mailing list (again thanks to Brett).
    So currently there is no way to get the return value from a dynamic replica slot in QML (QTBUG-77178)
    The reason i guess is that the QRemoteObjectPendingCall is not a QObject and cannot be exposed like that to QML.


  • Lifetime Qt Champion

    Thanks for the feedback !