Véhicule
Gérer deux connexions multithread entre un client Qt gRPC™ et un serveur C++ gRPC.
Cet exemple simule le tableau de bord d’un véhicule qui affiche les données envoyées par un serveur gRPC.

Le code d'exemple comporte les éléments suivants :
vehicle_clientUne application cliente Qt pour gRPC qui utilise les fonctions CMake ` qt_add_protobuf() ` et `qt_add_grpc() ` pour générer le code Qt des messages et des services.vehicle_serverUne application qui appelle le plugin C++ gRPC pour générer le code serveur et implémenter une logique serveur simple.
Remarque : le plugin C++ d’ gRPC doit être installé. Pour plus de détails, consultez la section « Prérequis des modules ».
Ces deux composants utilisent des messages générés à partir des schémas protobuf décrits dans les fichiers vehicleservice.proto et navigationservice.proto.
Service « Vehicle » :
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) {}
}Service de navigation :
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) {}
}Le singleton C++ de l’ VehicleManager utilise deux instances de type « QThread » pour communiquer en parallèle avec le serveur. Les threads disposent de différents types de connexion « gRPC ». Dans cet exemple, il en existe deux :
- RPC de streaming serveur Par exemple, le flux de vitesse du thread du véhicule. Il utilise deux fonctions de rappel : QGrpcServerStream::messageReceived et QGrpcOperation::finished
Empty speedRequest; m_streamSpeed = m_client->getSpeedStream(speedRequest); connect(m_streamSpeed.get(), &QGrpcServerStream::messageReceived, this, [this]() { if (const auto speedResponse = m_streamSpeed->read<SpeedMsg>()) { emit speedChanged(speedResponse->speed()); } }); connect( m_streamSpeed.get(), &QGrpcServerStream::finished, this, [this](const QGrpcStatus&status) { if (!status.isOk()) { auto error = QString("Erreur de flux lors de la récupération de la vitesse %1 (%2)") .arg(status.message()) .arg(QVariant::fromValue(status.code()).toString()); emit connectionError(error); qWarning() << error; return; } }, Qt::SingleShotConnection); RPC unaires de type « - » L'opération RPC «
getAutonomy» est un RPC unaire. Elle renvoie une seule réponse. Elle est uniquement connectée au signal « QGrpcOperation::finished ».autonomyRequest vide ; std::unique_ptr<QGrpcCallReply> autonomyReply = m_client->getAutonomy(autonomyRequest); const auto *autonomyReplyPtr = autonomyReply.get(); connect( autonomyReplyPtr, &QGrpcCallReply::finished, this, [this, autonomyReply = std::move(autonomyReply)](const QGrpcStatus&status) { if (!status.isOk()) { auto error = QString("Erreur lors de la récupération de l'autonomie %1 (%2)") .arg(status.message()) .arg(QVariant::fromValue(status.code()).toString()); emit connectionError(error); qWarning() << error; return; } if (const auto autonomyMsg = autonomyReply->read<AutonomyMsg>()) { emit autonomyChanged(autonomyMsg->autonomy()); } }, Qt::SingleShotConnection);
L'interface de la fenêtre principale du client est définie dans le fichier Main.qml. Elle utilise le type QML ` Connections ` afin de relier les signaux du singleton C++ ` VehicleManager ` à des slots personnalisés :
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 = "";
}
}Après avoir reçu une réponse, la fenêtre du client met à jour l’interface utilisateur avec les données reçues. De cette manière, les messages peuvent être reçus dans différents threads et transmis à l’interface utilisateur du client de manière thread-safe grâce aux signaux.
© 2026 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.