车辆

管理 Qt gRPC客户端和 C++gRPC 服务器之间的两个线程连接。

该示例模拟了一个车辆仪表盘,显示gRPC 服务器发送的数据。

车辆示例仪表板截图

示例代码包含以下组件:

  • vehicle_client Qt 客户端应用程序,使用gRPC qt_add_protobuf()qt_add_grpc()CMake 函数生成消息和服务 Qt 代码。
  • vehicle_server 调用 C++ 插件生成服务器代码并执行简单服务器逻辑的应用程序。gRPC

注意: 您需要安装 C++gRPC 插件。详情请点击此处:模块先决条件

两个组件都使用从文件vehicleservice.protonavigationservice.proto 中描述的 protobuf 模式生成的信息。

车辆服务:

message SpeedMsg {
    int32 speed = 1;
}

message RpmMsg {
    int32 rpm = 1;
}

message AutonomyMsg {
    int32 autonomy = 1;
}

service VehicleService {
    rpc getSpeedStream(google.protobuf.Empty) returns (stream SpeedMsg) {}
    rpc getRpmStream(google.protobuf.Empty) returns (stream RpmMsg) {}
    rpc getAutonomy(google.protobuf.Empty) returns (AutonomyMsg) {}
}

导航服务

enum DirectionEnum {
    RIGHT = 0;
    LEFT = 1;
    STRAIGHT = 2;
    BACKWARD = 3;
}

message NavigationMsg {
    int32 totalDistance = 1;
    int32 traveledDistance = 2;
    DirectionEnum direction = 3;
    string street = 4;
}

service NavigationService {
    rpc getNavigationStream(google.protobuf.Empty) returns (stream NavigationMsg) {}
}

VehicleManager C++ 单例使用两个QThread 实例与服务器并行通信。这些线程具有不同的gRPC 连接类型。本例中有两种类型:

  • 服务器流 RPC 例如,车辆线程的速度流。它使用两个回调函数:QGrpcServerStream::messageReceivedQGrpcOperation::finished
    Empty speedRequest; m_streamSpeed=  m_client->getSpeedStream(speedRequest); connect(m_streamSpeed.get(), &QGrpcServerStream::messageReceived, this, [this]() {if(const autospeedResponse=  m_streamSpeed->read<SpeedMsg>()) {emitspeedChanged(speedResponse->speed()); } }); connect( m_streamSpeed.get(), &QGrpcServerStream::finished, this,[this](constQGrpcStatus&status) {if(!status.isOk()) {autoerror=QString("Stream error fetching speed %1 (%2)").arg(status.message()).arg(QVariant::fromValue(status.code()).toString());emitconnectionError(error);            qWarning() << error;
               return; }}    Qt::SingleShotConnection);
  • 一元 RPC RPCgetAutonomy 操作是一元 RPC。它只返回一个响应。它只与QGrpcOperation::finished 信号相连。
     autonomyRequest; std::unique_ptr<QGrpcCallReply>autonomyReply=  m_client->getAutonomy(autonomyRequest);const auto *autonomyReplyPtr =autonomyReply.get(); connect( autonomyReplyPtr, &QGrpcCallReply::finished, this,[this,autonomyReply=std::move(autonomyReply)](constQGrpcStatus&status) {if(!status.isOk()) {autoerror=QString("Call error fetching autonomy %1 (%2)").arg(status.message()).arg(QVariant::fromValue(status.code()).toString());emitconnectionError(error);            qWarning() << error;
               return; }if(const autoautonomyMsg=  autonomyReply->read<AutonomyMsg>()) {emitautonomyChanged(autonomyMsg->autonomy()); }}    Qt::SingleShotConnection);

客户端主窗口界面在 Main.qml 文件中定义。它使用 QMLConnections 类型,以便将VehicleManager C++ 单例的信号连接到自定义插槽:

    Connections {
        target: VehicleManager

        // This slot will be executed when the VehicleManager::totalDistanceChanged
        // signal is emitted
        function onTotalDistanceChanged(distance: int): void {
            root.totalDistance = distance;
        }

        function onSpeedChanged(speed: int): void {
            root.speed = speed;
        }

        function onRpmChanged(rpm: int): void {
            root.rpm = rpm;
        }

        function onTraveledDistanceChanged(distance: int): void {
            root.traveledDistance = distance;
        }

        function onDirectionChanged(direction: int): void {
            if (direction == VehicleManager.RIGHT) {
                root.directionImageSource = "qrc:/direction_right.svg";
            } else if (direction == VehicleManager.LEFT) {
                root.directionImageSource =  "qrc:/direction_left.svg";
            } else if (direction == VehicleManager.STRAIGHT) {
                root.directionImageSource =  "qrc:/direction_straight.svg";
            } else {
                root.directionImageSource =  "";
            }
        }

收到响应后,客户端窗口会用收到的数据更新用户界面。这样,信息就能在不同线程中接收,并通过信号以线程安全的方式发送到客户端用户界面。

示例项目 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.