範例 1:使用靜態源直接連接

  1. 創建源對象

    要創建此 Source 對象,首先創建定義文件 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 (復本編譯器) 處理此文件,把以下行添加到 .pro 文件:

    REPC_SOURCE = simpleswitch.rep
    							

    The REPC_SOURCE 變量隻與 Qt Remote Objects 模塊相關,所以也需要把它添加到工程:

    QT       += remoteobjects
    							

    RepC (復本編譯器) 創建 rep_SimpleSwitch_source.h 頭在指定的構建目錄下。更多信息,見 Source .

    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();
        virtual void server_slot(bool clientState);
    public Q_SLOTS:
        void timeout_slot();
    private:
        QTimer *stateChangeTimer;
    };
    #endif
    							

    simpleswitch.h ,

    • stateChangeTimer QTimer 用於觸發 SimpleSwitch 狀態。
    • timeout_slot() 被連接到 stateChangeTimer 的 timeout() 信號。
    • server_slot() -- 在 Source (源) 中被自動調用,每當任何復本調用其槽版本時 -- 輸齣接收值。
    • 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, &SimpleSwitch::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:switch")));
    							
  4. 主機源對象和遠程

    下列語句實例化 Source 對象並把它傳遞給主機以啓用 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
        QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:switch"))); // create host node without Registry
        srcNode.enableRemoting(&srcSwitch); // enable remoting/sharing
        return a.exec();
    }
    							

    編譯並運行此 Source (源) 側工程。在不創建任何 Replica (復本) 的情況下,輸齣看起來應該如下所示,采用開關狀態觸發介於 true and false 每隔 2 秒。

    "Example 1: Server Output"

後續步驟是創建網絡的 Replica (復本) 側。在此範例中,獲取開關狀態來自 Source 並迴顯它。

復本代碼

  1. 使用 RepC (復本編譯器) 將 Replica (復本) 添加到工程

    使用如 Source (源) 側所做的相同 API 定義文件 SimpleSwitch.rep ,要創建 復本 頭文件使用 repc 。包括以下行在客戶端側 .pro 文件,指定 .rep 文件輸入:

    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:switch"))); // connect with remote host node
    							
  3. 調用節點的 acquire() 創建復本指針

    首先,實例化復本:

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

    注意: acquire() 返迴 Replica (復本) 指針,但不管理其壽命。此範例展示包裹返迴指針的推薦進程在 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:switch"))); // 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();
        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(); // 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)
    {
        initConnections();
        //We can connect to SimpleSwitchReplica Signals/Slots
        //directly because our Replica was generated by repc.
    }
    //destructor
    Client::~Client()
    {
    }
    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()
    {
        qDebug() << "Received source state "<<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"