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操作的客户端来触发远程接口调用。

ZfvPxs52M-sZ71EQxNvEIhqEzOnWjSJZPzTBJKYVzlQ.png

定义接口

为了能够实现两个进程间的远程过程调用,我们需要定义他们之间的通信标准。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);

}

演示效果

先打开服务端的控制台程序,然后打开客户端,在客户端中输入消息点击发送。发送成功的话就可以收到客户端反转后的消息。

nRhTfz4fsDZSSLdl2sZi9CuL35lOBcDaR00rBt2eJlk.gif

参考

https://blog.csdn.net/luoyayun361/article/details/91588654