范例 1:使用静态源直接连接

  1. 创建源对象

    要创建此 对象,首先创建定义文件 simpleswitch.rep 。此文件描述对象的特性和方法,并被输入到 Qt Remote Objects 编译器 repc 。此文件只定义必要暴露接口给 复本 .

    simpleswitch.rep

    class SimpleSwitch
    {
        PROP(bool currState=false);
        SLOT(server_slot(bool clientState));
    };
    							

    simpleswitch.rep ,

    • currState 保持开关的当前状态。
    • server_slot() 允许我们与 Source (源) 交互 - 将把它连接到 echoSwitchState(bool newstate) 信号。

    为使 RepC (复本编译器) 处理此文件,把以下行添加到 cmake 文件:

    qt6_add_repc_sources(directconnectserver
        simpleswitch.rep
    )
    							

    若正使用 qmake :

    REPC_SOURCE = simpleswitch.rep
    							

    These instructions are only relevant for the Qt Remote Object module, so you need to add it to your project as well. If you're using CMake, add:

    find_package(Qt6 REQUIRED COMPONENTS RemoteObjects)
    target_link_libraries(directconnectserver PRIVATE Qt6::RemoteObjects)
    							

    若正使用 qmake :

    QT       += remoteobjects
    							

    RepC (复本编译器) 创建 rep_SimpleSwitch_source.h 头在指定的构建目录下。更多信息,见 .

    RepC (复本编译器) 创建了 3 个帮手类为用于 QtRO。对于此范例,我们使用基本: SimpleSwitchSimpleSource 。它是抽象类,定义在 rep_SimpleSwitch_source.h 。从它派生以定义 SimpleSwitch 实现类,如下所示:

    simpleswitch.h

    #ifndef SIMPLESWITCH_H
    #define SIMPLESWITCH_H
    #include "rep_simpleswitch_source.h"
    class SimpleSwitch : public SimpleSwitchSimpleSource
    {
        Q_OBJECT
    public:
        SimpleSwitch(QObject *parent = nullptr);
        ~SimpleSwitch();
        void server_slot(bool clientState) override;
    public Q_SLOTS:
        void timeout_slot();
    private:
        QTimer *stateChangeTimer;
    };
    #endif
    							

    simpleswitch.h ,

    • stateChangeTimer QTimer 用于触发 SimpleSwitch 状态。
    • timeout_slot() 被连接到 stateChangeTimer 的 timeout() 信号。
    • server_slot() – which is called automatically on the source whenever any replica calls their version of the slot – outputs the received value.
    • currStateChanged(bool) ,定义在 repc 生成 rep_SimpleSwitch_source.h ,被发射每当 currState 触发。在此范例中,我们忽略 Source (源) 侧信号,并稍后在 Replica (复本) 侧处理它。

    定义的 SwitchState 类展示如下:

    simpleswitch.cpp

    #include "simpleswitch.h"
    // constructor
    SimpleSwitch::SimpleSwitch(QObject *parent) : SimpleSwitchSimpleSource(parent)
    {
        stateChangeTimer = new QTimer(this); // Initialize timer
        QObject::connect(stateChangeTimer, &QTimer::timeout, this, &SimpleSwitch::timeout_slot); // connect timeout() signal from stateChangeTimer to timeout_slot() of simpleSwitch
        stateChangeTimer->start(2000); // Start timer and set timout to 2 seconds
        qDebug() << "Source Node Started";
    }
    //destructor
    SimpleSwitch::~SimpleSwitch()
    {
        stateChangeTimer->stop();
    }
    void SimpleSwitch::server_slot(bool clientState)
    {
        qDebug() << "Replica state is " << clientState; // print switch state echoed back by client
    }
    void SimpleSwitch::timeout_slot()
    {
        // slot called on timer timeout
        if (currState()) // check if current state is true, currState() is defined in repc generated rep_simpleswitch_source.h
            setCurrState(false); // set state to false
        else
            setCurrState(true); // set state to true
        qDebug() << "Source State is "<<currState();
    }
    							
  2. 创建注册

    由于这个范例在节点之间使用了直接连接,所以可以省略此步骤。

  3. 创建主机节点

    主机节点的创建如下所示:

    QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
    							
  4. 主机源对象和远程

    下列语句实例化 对象并把它传递给主机以启用 remoting,这是使对象对 QtRO 网络可见的过程:

    SimpleSwitch srcSwitch; // create simple switch
    srcNode.enableRemoting(&srcSwitch); // enable remoting
    							

    内容对于 main.cpp 文件,实现上述步骤如下:

    main.cpp

    #include <QCoreApplication>
    #include "simpleswitch.h"
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        SimpleSwitch srcSwitch; // create simple switch
        // Create host node without Registry:
        QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
        srcNode.enableRemoting(&srcSwitch); // enable remoting/sharing
        return a.exec();
    }
    							

    编译并运行此 Source (源) 侧工程。在不创建任何 Replica (复本) 的情况下,输出看起来应该如下所示,采用开关状态触发介于 true and false 每隔 2 秒。

    "Example 1: Server Output"

后续步骤是创建网络的 Replica (复本) 侧。在此范例中,获取开关状态来自 并回显它。

复本代码

  1. 使用 RepC (复本编译器) 将 Replica (复本) 添加到工程

    使用如 Source (源) 侧所做的相同 API 定义文件 SimpleSwitch.rep ,要创建 复本 头文件使用 repc . If you're using cmake , include the following line in your client side cmake 文件,指定 .rep 文件输入:

    qt6_add_repc_replicas(directconnectclient
        simpleswitch.rep
    )
    							

    若正使用 qmake , add the following line to your client side .pro 文件:

    REPC_REPLICA = simpleswitch.rep
    							

    The repc 工具生成 rep_SimpleSwitch_replica.h 文件在构建目录下。更多信息,见 复本 .

  2. 创建连接 Source (源) 主机节点的节点

    以下代码实例化网络中的第 2 节点,并把它连接到 Source (源) 主机节点:

    QRemoteObjectNode repNode; // create remote object node
    repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); // connect with remote host node
    							
  3. 调用节点的 acquire () to create a pointer to a replica

    首先,实例化复本:

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

    注意: 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 以确保始终正确删除指针。

    main.cpp 实现上述步骤并实例化对象:

    main.cpp

    #include <QCoreApplication>
    #include "client.h"
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        QSharedPointer<SimpleSwitchReplica> ptr; // shared pointer to hold source replica
        QRemoteObjectNode repNode; // create remote object node
        repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); // connect with remote host node
        ptr.reset(repNode.acquire<SimpleSwitchReplica>()); // acquire replica of source from host node
        Client rswitch(ptr); // create client switch object and pass reference of replica to it
        return a.exec();
    }
    							

    完整声明和定义对于 Client 类如下:

    client.h

    #ifndef _CLIENT_H
    #define _CLIENT_H
    #include <QObject>
    #include <QSharedPointer>
    #include "rep_simpleswitch_replica.h"
    class Client : public QObject
    {
        Q_OBJECT
    public:
        Client(QSharedPointer<SimpleSwitchReplica> ptr);
        ~Client() override = default;
        void initConnections();// Function to connect signals and slots of source and client
    Q_SIGNALS:
        void echoSwitchState(bool switchState);// this signal is connected with server_slot(..) on the source object and echoes back switch state received from source
    public Q_SLOTS:
        void recSwitchState_slot(bool); // slot to receive source state
    private:
        bool clientSwitchState; // holds received server switch state
        QSharedPointer<SimpleSwitchReplica> reptr;// holds reference to replica
     };
    #endif
    							

    client.cpp

    #include "client.h"
    // constructor
    Client::Client(QSharedPointer<SimpleSwitchReplica> ptr) :
        QObject(nullptr),reptr(ptr)
    {
        // Connect signal for replica initialized with initialization slot.
        initConnections();
        // We can connect to SimpleSwitchReplica Signals/Slots
        // directly because our Replica was generated by repc.
    }
    void Client::initConnections()
    {
        // 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, this, &Client::recSwitchState_slot);
        // connect client's echoSwitchState(..) signal with replica's server_slot(..) to echo back received state
        QObject::connect(this, &Client::echoSwitchState, reptr.data(), &SimpleSwitchReplica::server_slot);
    }
    void Client::recSwitchState_slot(bool value)
    {
        qDebug() << "Received source state "<< value << reptr.data()->currState();
        clientSwitchState = reptr.data()->currState();
        Q_EMIT echoSwitchState(clientSwitchState); // Emit signal to echo received state back to server
    }
    							

    编译并运行此示例,与 Source (源) 侧范例一起生成以下输出:

    "Direct Connect Server Client Communication output"