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 fichier .proto simple 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 en C

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

scalars_example.c
#include <stdio.h>
#include <stdint.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 un 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("Encoding failed: %s\n", PB_GET_ERROR(&ostream));
        return 1;
    }
    
    message_length = ostream.bytes_written;
    printf("Encoded %zu bytes\n", message_length);
    
    // Afficher le dump hexadécimal des données encodées
    printf("Encoded data: ");
    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 un 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("Decoding failed: %s\n", PB_GET_ERROR(&istream));
        return 1;
    }
    
    // Afficher les valeurs décodées
    printf("Decoded values:\n");
    printf("  uint32_value: %u\n", (unsigned int)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
gcc -o scalars_example scalars_example.c 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 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("Python decoded values:")
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.c
// 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

Différences par rapport au C++

La version C est presque identique à la version C++, avec seulement des différences mineures :

Plus d’articles sur NanoPB


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