Example 1: Direct Connection using a Static Source

Describes how the Qt Remote Objects establishes a direct connection using a static source. .. _qtro-example1: In this example, the source object is a simple binary switch that toggles its state based on a timer. When the state changes, a signal is emitted by the source which QtRO propagates to all replicas. Since the replicas have the same properties, signals, and slots as were exposed from the source, any slots connected to the replica’s signal will be called when the replica receives that signal. The client process then echoes back the received switch state to the source by emitting its own signal which is connected to a slot on the replica.

  • Create a registry

    Because this example uses a direct connection between nodes, we can omit this step.

  • Create a host node

    The host node is created as shown below:

    srcNode = QRemoteObjectHost(QUrl(QStringLiteral("local:switch")))
    
  • Host source object and remoting

    The following statements instantiate the Source object and pass it on to the host to enable “remoting”, which is the process of making an object visible to the QtRO network:

    srcSwitch = SimpleSwitch()
    srcNode.enableRemoting(srcSwitch) # enable remoting
    

    The contents of main.cpp file that implements the steps described above are as follows:

    main.cpp

    from PySide6.QtCore import QCoreApplication
    from simpleswitch import *
    if __name__ == "__main__":
    
        a = QCoreApplication(argc, argv)
        srcSwitch = SimpleSwitch()
        srcNode = QRemoteObjectHost(QUrl(QStringLiteral("local:switch")))
        srcNode.enableRemoting(srcSwitch) # enable remoting/sharing
        return a.exec()
    

    Compile and run this source-side project. The output, without any replicas created, should look as shown below with the switch state toggling between true and false every two seconds.

    ../_images/DirectConnectServerOutput.png

The subsequent steps are for creating the replica side of the network, which in this example gets the state of switch from the Source and echoes it back.

Replica Code

  1. Use repc to add a replica to your project

    We use the same API definition file as we did on the source side, SimpleSwitch.rep, to create a Replica header file using the repc . If you’re using cmake, include the following line in your client side cmake file, specifying a .rep file input:

    <Code snippet "cmake-macros/CMakeLists.txt:simpleSwitch_cmake_add_repc_replica" not found>
    

    If you’re using qmake, add the following line to your client side .pro file:

    REPC_REPLICA = simpleswitch.rep
    

    The repc tool generates a rep_SimpleSwitch_replica.h file in the build directory. For more information, see Replica .

  2. Create a node to connect with the source’s host node

    The following code instantiates the second node on the network and connects it with the source host node:

    repNode = QRemoteObjectNode()
    repNode.connectToNode(QUrl(QStringLiteral("local:switch"))) # connect with remote host node
    
  3. Call the node’s acquire() to create a pointer to a replica

    First, we instantiate a replica:

    ptr = QSharedPointer()
    ptr.reset(repNode.acquire<SimpleSwitchReplica>()) # acquire replica of source from host node
    

    Note

    acquire() returns a pointer to the replica, but doesn’t manage its lifetime. This example shows the recommended process of wrapping the returned pointer in a QSharedPointer or QScopedPointer to ensure that the pointer is always deleted properly.

    main.cpp implements the steps described above and instantiates our object:

    main.cpp

    from PySide6.QtCore import QCoreApplication
    from client import *
    if __name__ == "__main__":
    
        a = QCoreApplication(argc, argv)
    ptr = QSharedPointer()
        repNode = QRemoteObjectNode()
        repNode.connectToNode(QUrl(QStringLiteral("local:switch"))) # connect with remote host node
        ptr.reset(repNode.acquire<SimpleSwitchReplica>()) # acquire replica of source from host node
        rswitch = Client(ptr)
        return a.exec()
    

    The complete declaration and definition for the Client class is as follows:

    client.h

    #ifndef _CLIENT_H
    #define _CLIENT_H
    from PySide6.QtCore import QObject
    
    from rep_simpleswitch_replica import *
    class Client(QObject):
    
        Q_OBJECT
    # public
        Client(QSharedPointer<SimpleSwitchReplica> ptr)
        ~Client()
        def initConnections():
    Q_SIGNALS:
        def echoSwitchState(server_slot(..):
    Q_SLOTS: = public()
        def recSwitchState_slot():
    # private
        clientSwitchState = bool()
    reptr# = QSharedPointer()
    
    #endif
    

    client.cpp

    from client import *
    # constructor
    def __init__(self, ptr):
        QObject(None),reptr(ptr)
    
        initConnections()
        #We can connect to SimpleSwitchReplica Signals/Slots
        #directly because our Replica was generated by repc.
    
    #destructor
    Client::~Client()
    
    
    def initConnections(self):
    
        # initialize connections between signals and slots
        # connect source replica signal currStateChanged() with client's recSwitchState() slot to receive source's current state
        QObject.connect(reptr.data(), SimpleSwitchReplica.currStateChanged, self, Client.recSwitchState_slot)
        # connect client's echoSwitchState(..) signal with replica's server_slot(..) to echo back received state
        QObject.connect(self, Client.echoSwitchState, reptr.data(), SimpleSwitchReplica.server_slot)
    
    def recSwitchState_slot(self, value):
    
        print("Received source state ", value, reptr.data().currState())
        clientSwitchState = reptr.data().currState()
        Q_EMIT echoSwitchState(clientSwitchState) # Emit signal to echo received state back to server
    

    Compiling and running this example together with the source-side example generates the following output:

    ../_images/DirectConnectClientServerOutput.png