NanoPB: Comment gérer les types scalaires de base en C++

English Français

Voir aussi : Version C : Comment gérer les types scalaires de base en C

NanoPB est une implémentation de Protocol Buffers optimisée pour la taille du code, destinée aux systèmes embarqués. Cet article montre comment gérer les types scalaires de base (entiers, flottants, booléens) en C++ avec NanoPB.

Définition Proto

Créez d’abord un simple fichier .proto avec des types scalaires de base :

scalars.proto
syntax = "proto3";

package example;

message ScalarMessage {
  uint32 uint32_value = 1;
  uint64 uint64_value = 2;
  int32 int32_value = 3;
  int64 int64_value = 4;
  float float_value = 5;
  bool bool_value = 6;
}

Générer le code NanoPB

Générez le code C++ NanoPB en utilisant le générateur nanopb :

generate_nanopb_scalars.sh
protoc --nanopb_out=. scalars.proto

Cela générera scalars.pb.h et scalars.pb.c.

Exemple C++

Voici un exemple C++ complet qui encode et décode le message :

scalars_example.cpp
#include <stdio.h>
#include <string.h>
#include "scalars.pb.h"
#include "pb_encode.h"
#include "pb_decode.h"

int main() {
    // Tampon pour le message encodé
    uint8_t buffer[128];
    size_t message_length;
    
    // --- ENCODAGE ---
    example_ScalarMessage message = example_ScalarMessage_init_zero;
    
    // Définir les valeurs des champs
    message.uint32_value = 42;
    message.uint64_value = 1234567890ULL;
    message.int32_value = -100;
    message.int64_value = -9876543210LL;
    message.float_value = 3.14159f;
    message.bool_value = true;
    
    // Créer le flux pour l'encodage
    pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
    
    // Encoder le message
    if (!pb_encode(&ostream, example_ScalarMessage_fields, &message)) {
        printf("Échec de l'encodage : %s\n", PB_GET_ERROR(&ostream));
        return 1;
    }
    
    message_length = ostream.bytes_written;
    printf("Encodé %zu octets\n", message_length);
    
    // Afficher le dump hexadécimal des données encodées
    printf("Données encodées : ");
    for (size_t i = 0; i < message_length; i++) {
        printf("%02x ", buffer[i]);
    }
    printf("\n");
    
    // --- DÉCODAGE ---
    example_ScalarMessage decoded = example_ScalarMessage_init_zero;
    
    // Créer le flux pour le décodage
    pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
    
    // Décoder le message
    if (!pb_decode(&istream, example_ScalarMessage_fields, &decoded)) {
        printf("Échec du décodage : %s\n", PB_GET_ERROR(&istream));
        return 1;
    }
    
    // Afficher les valeurs décodées
    printf("Valeurs décodées :\n");
    printf("  uint32_value : %u\n", decoded.uint32_value);
    printf("  uint64_value : %llu\n", (unsigned long long)decoded.uint64_value);
    printf("  int32_value : %d\n", decoded.int32_value);
    printf("  int64_value : %lld\n", (long long)decoded.int64_value);
    printf("  float_value : %f\n", decoded.float_value);
    printf("  bool_value : %s\n", decoded.bool_value ? "true" : "false");
    
    return 0;
}

Commande de compilation

Compilez l’exemple avec nanopb. NanoPB est généralement utilisé en incluant directement les fichiers sources dans votre projet :

compile_scalars_example.sh
g++ -o scalars_example scalars_example.cpp scalars.pb.c pb_common.c pb_encode.c pb_decode.c -I.

Remarque : Les fichiers sources NanoPB (pb_common.c, pb_encode.c, pb_decode.c) doivent être compilés directement avec votre projet. Vous pouvez les obtenir depuis le dépôt GitHub de NanoPB.

Script de test Python

Pour vérifier l’encodage, vous pouvez utiliser la bibliothèque protobuf de Python :

test_scalars.py
import scalars_pb2

# Lire les données binaires
with open('encoded.bin', 'rb') as f:
    data = f.read()

# Décoder
msg = scalars_pb2.ScalarMessage()
msg.ParseFromString(data)

print("Valeurs décodées par Python :")
print(f"  uint32_value : {msg.uint32_value}")
print(f"  uint64_value : {msg.uint64_value}")
print(f"  int32_value : {msg.int32_value}")
print(f"  int64_value : {msg.int64_value}")
print(f"  float_value : {msg.float_value}")
print(f"  bool_value : {msg.bool_value}")

Compilez d’abord les définitions protobuf Python :

compile_python_scalars.sh
protoc --python_out=. scalars.proto

Modifiez ensuite l’exemple C++ pour enregistrer les données encodées dans un fichier :

save_encoded_scalars.cpp
// Après l'encodage, ajoutez ceci :
FILE *f = fopen("encoded.bin", "wb");
fwrite(buffer, 1, message_length, f);
fclose(f);

Points clés

Sortie attendue

scalars_expected_output.txt
Encoded 28 bytes
Encoded data: 08 2a 10 d2 95 89 04 18 9c ff ff ff ff ff ff ff 01 20 c6 ef be ad de 05 2d 15 49 0e 40 30 01 
Decoded values:
  uint32_value: 42
  uint64_value: 1234567890
  int32_value: -100
  int64_value: -9876543210
  float_value: 3.141590
  bool_value: true

Plus d’articles sur NanoPB


Check out similar posts by category: Embedded, C/C++, Protocol Buffers