Qt Remote Objects实现进程间调用
The Qt Remote Objects module provides an easy way to share Qt APIs between processes and devices. For this to work, we require a data channel between processes and devices.
根据Qt 5.15.2 官方手册介绍, Qt Remote Objects提供了一种简单的在进程间或者设备间共享Qt API的方式,类似于gRPC的远程过程调用。但个人感觉比gRPC简单许多。本文将介绍QtRO的简单使用。
完整项目代码:Github
创建项目接口
首先创建如下的项目结构,需要一个服务端,我们这里为了方便选用控制台来演示,一个支持GUI操作的客户端来触发远程接口调用。
定义接口
为了能够实现两个进程间的远程过程调用,我们需要定义他们之间的通信标准。QtRO定义了一种声明通信接口的语法规则,来声明API接口模型,并通过特定的代码生成器生成客户端和服务端的接口。
我们定义一个最简单的接口 SimpleRO.rep
class SimpleROInterface
{
SIGNAL(message(QString msg)) // send message to client
SLOT(void onMessage(QString msg)) // receive message from client
}
将定义的接口文件添加到客户端和服务端项目中
在客户端的QMake配置文件中加入如下的配置
REPC_REPLICA += \
../common/SimpleRO.rep
在服务端的QMake配置文件中加入如下的配置
REPC_SOURCE += \
../common/SimpleRO.rep
注意:客户端和服务端是不一样的,用于告诉QMake生成不同的客户端和服务端代码
实现服务端功能类
新增一个SimpleROInterface
类实现接口中定义的功能
#ifndef SIMPLEROINTERFACE_H
#define SIMPLEROINTERFACE_H
#include <QObject>
#include "rep_SimpleRO_source.h"
class SimpleROInterface : public SimpleROInterfaceSource
{
Q_OBJECT
public:
explicit SimpleROInterface(QObject *parent = nullptr);
void sendMessage(const QString& message);
public Q_SLOTS:
virtual void onMessage(const QString& message) override;
};
#endif // SIMPLEROINTERFACE_H
#include "SimpleROInterface.h"
#include <QDebug>
SimpleROInterface::SimpleROInterface(QObject *parent)
: SimpleROInterfaceSource{parent}
{
}
void SimpleROInterface::sendMessage(const QString &_message)
{
Q_EMIT message(_message);
}
void SimpleROInterface::onMessage(const QString &message)
{
qDebug() << "Client -> Server Message:" << message;
QString flipMessage = message;
std::reverse(flipMessage.begin(), flipMessage.end());
sendMessage(flipMessage);
}
在main.cpp
中增加QRemoteObjectHost
的监听
#include <QCoreApplication>
#include <QRemoteObjectHost>
#include "SimpleROInterface.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
auto host = new QRemoteObjectHost(&a);
host->setHostUrl(QUrl("local:interfaces"));
auto interface = new SimpleROInterface(&a);
host->enableRemoting(interface);
return a.exec();
}
实现客户端功能
客户端比服务端简单许多,代码生成器替我们完成了大部分工作,我们只需要连接服务器,并实现功能逻辑即可。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QRemoteObjectNode>
#include "rep_SimpleRO_replica.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QRemoteObjectNode* mRemoteNode;
SimpleROInterfaceReplica* mSimpleROInterface;
private Q_SLOTS:
void onReceivedMessage(const QString& message);
void on_PB_SEND_clicked();
};
#endif // MAINWINDOW_H
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
mRemoteNode = new QRemoteObjectNode(this);
qDebug() << "Connected: " << mRemoteNode->connectToNode(QUrl("local:interfaces"));
mSimpleROInterface = mRemoteNode->acquire<SimpleROInterfaceReplica>();
connect(mSimpleROInterface, &SimpleROInterfaceReplica::message, this, &MainWindow::onReceivedMessage);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onReceivedMessage(const QString &message)
{
const QString str = QString("Server -> Client:").append(message);
qDebug() << str;
ui->TXT->append(str);
}
void MainWindow::on_PB_SEND_clicked()
{
const QString message = ui->LE_MSG->text();
if (message.isEmpty()) {
return;
}
mSimpleROInterface->onMessage(message);
const QString str = QString("Client -> Server:").append(message);
ui->TXT->append(str);
}
演示效果
先打开服务端的控制台程序,然后打开客户端,在客户端中输入消息点击发送。发送成功的话就可以收到客户端反转后的消息。
参考
感谢扫码支持