例 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 の状態を切り替えるのに使われます。QTimertimeout_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(); }
- レジストリの作成
この例ではノード間の直接接続を使用しているため、このステップは省略できます。
- ホスト・ノードの作成
以下のようにホスト・ノードを作成します:
QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
- ホストのソース・オブジェクトとリモーティング
以下のステートメントでは、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秒ごとにスイッチの状態が
true
とfalse
の間で切り替わり、以下のようになるはずです。
この例では、ソースからスイッチの状態を取得し、それをエコーバックしている。
レプリカコード
- 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 番目のノードをインスタンス化し、ソース・ホスト・ノードと接続します:
QRemoteObjectNode repNode; // create remote object node repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); // connect with remote host node
- ノードのacquire() を呼び出して、レプリカへのポインタを作成します。
まず、レプリカをインスタンス化します:
QSharedPointer<SimpleSwitchReplica> ptr; ptr.reset(repNode.acquire<SimpleSwitchReplica>()); // acquire replica of source from host node
注: acquire() はレプリカへのポインタを返しますが、その寿命は管理しません。この例では、返されたポインタをQSharedPointer や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 }
この例をソース側の例と一緒にコンパイルして実行すると、次のような出力が生成される:
この例とソース側の例を一緒にコンパイルすると、次のような出力が得られます©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。