要创建此
源
对象,首先创建定义文件
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
头在指定的构建目录下。更多信息,见
源
.
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(); }
由于这个范例在节点之间使用了直接连接,所以可以省略此步骤。
主机节点的创建如下所示:
QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:switch")));
下列语句实例化 源 对象并把它传递给主机以启用 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 秒。
后续步骤是创建网络的 Replica (复本) 侧。在此范例中,获取开关状态来自 源 并回显它。
使用如 Source (源) 侧所做的相同 API 定义文件
SimpleSwitch.rep
,要创建
复本
头文件使用
repc
。包括以下行在客户端侧
.pro
文件,指定
.rep
文件输入:
REPC_REPLICA = simpleswitch.rep
The
repc
工具生成
rep_SimpleSwitch_replica.h
文件在构建目录下。更多信息,见
复本
.
以下代码实例化网络中的第 2 节点,并把它连接到 Source (源) 主机节点:
QRemoteObjectNode repNode; // create remote object node repNode.connectToNode(QUrl(QStringLiteral("local:switch"))); // connect with remote host node
首先,实例化复本:
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 (源) 侧范例一起生成以下输出: