例 1:静的ソースを使用した直接接続

  1. ソース・オブジェクトの作成

    このSourceオブジェクトを作成するために、まず定義ファイルsimpleswitch.rep を作成します。このファイルには、オブジェクトのプロパティとメソッドが記述され、Qt Remote Objects Compilerrepc への入力となります。このファイルには、レプリカに公開するために必要なインターフェイスのみが定義されています。

    simpleswitch.rep

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

    simpleswitch.rep にあります、

    • currState はスイッチの現在の状態を保持する。
    • server_slot() これは、 信号に接続される。echoSwitchState(bool newstate)

    repc がこのファイルを処理するには、cmake ファイルに以下の行を追加します:

    qt6_add_repc_sources(directconnectserver
        simpleswitch.rep
    )

    qmake

    REPC_SOURCE = simpleswitch.rep

    これらの説明は Qt Remote Object モジュールにのみ関係しますので、あなたのプロジェクトにも追加する必要があります。CMakeを使用している場合は、以下を追加してください:

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

    qmake を使っている場合は、以下を追加してください:

    QT       += remoteobjects

    repc は指定したビルドディレクトリにrep_SimpleSwitch_source.h ヘッダーを作成します。詳細については、ソースを参照してください。

    repc は QtRO で使用する 3 つのヘルパークラスを作成します。この例では、基本的なものを使います: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 は で、SimpleSwitch の状態を切り替えるのに使われます。QTimer
    • timeout_slot() は の timeout() シグナルに接続されています。stateChangeTimer
    • server_slot() - このシグナルは、レプリカがスロットのバージョンを呼び出すたびに、ソース上で自動的に呼び出されます。
    • currStateChanged(bool) rep_SimpleSwitch_source.hこのシグナルは currState がトグルするたびに出力されます。この例では、ソース側でこのシグナルを無視し、後でレプリカ側で処理します。

    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. ホストのソース・オブジェクトとリモーティング

    以下のステートメントでは、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
    
        // Create host node without Registry:
        QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
        srcNode.enableRemoting(&srcSwitch); // enable remoting/sharing
    
        return a.exec();
    }

    このソース側プロジェクトをコンパイルして実行する。出力は、レプリカが作成されていない状態で、2秒ごとにスイッチの状態がtruefalse の間で切り替わり、以下のようになるはずです。

    "Example 1: Server Output"

この例では、ソースからスイッチの状態を取得し、それをエコーバックしている。

レプリカコード

  1. repcを使ってレプリカをプロジェクトに追加する

    ソース側で行ったのと同じAPI定義ファイル、SimpleSwitch.rep を使用して、repcを使用してReplicaヘッダーファイルを作成します。cmake を使用している場合は、クライアント側のcmake ファイルに以下の行を記述し、.rep ファイルの入力を指定します:

    qt6_add_repc_replicas(directconnectclient
        simpleswitch.rep
    )

    qmake を使用している場合は、クライアント側の.pro ファイルに以下の行を追加します:

    REPC_REPLICA = simpleswitch.rep

    repcツールはビルド・ディレクトリにrep_SimpleSwitch_replica.h ファイルを生成します。詳細については、Replicaを参照してください。

  2. ソースのホスト・ノードと接続するノードの作成

    以下のコードは、ネットワーク上の 2 番目のノードをインスタンス化し、ソース・ホスト・ノードと接続します:

    QRemoteObjectNode repNode; // create remote object node
    repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); // connect with remote host node
  3. ノードのacquire() を呼び出して、レプリカへのポインタを作成します。

    まず、レプリカをインスタンス化します:

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

    注: acquire() はレプリカへのポインタを返しますが、その寿命は管理しません。この例では、返されたポインタをQSharedPointerQScopedPointer でラップして、ポインタが常に適切に削除されるようにすることを推奨しています。

    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
    }

    この例をソース側の例と一緒にコンパイルして実行すると、次のような出力が生成される:

    "Direct Connect Server Client Communication output"

この例とソース側の例を一緒にコンパイルすると、次のような出力が得られます©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。