NanoPB: Як обробляти базові скалярні типи в C++

Див. також: Версія на C: Як обробляти базові скалярні типи в C

NanoPB — це оптимізована за розміром коду реалізація Protocol Buffers для вбудованих систем. Ця публікація показує, як обробляти базові скалярні типи (цілі числа, числа з рухомою комою, булеві значення) в C++ за допомогою NanoPB.

Визначення Proto

Спочатку створіть простий файл .proto з базовими скалярними типами:

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;
}

Генерація коду NanoPB

Згенеруйте код NanoPB для C++ за допомогою генератора nanopb:

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

Це згенерує scalars.pb.h та scalars.pb.c.

Приклад на C++

Ось повний приклад на C++, який кодує та декодує повідомлення:

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

int main() {
    // Буфер для закодованого повідомлення
    uint8_t buffer[128];
    size_t message_length;
    
    // --- КОДУВАННЯ ---
    example_ScalarMessage message = example_ScalarMessage_init_zero;
    
    // Встановлення значень полів
    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;
    
    // Створення потоку для кодування
    pb_ostream_t ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
    
    // Кодування повідомлення
    if (!pb_encode(&ostream, example_ScalarMessage_fields, &message)) {
        printf("Помилка кодування: %s\n", PB_GET_ERROR(&ostream));
        return 1;
    }
    
    message_length = ostream.bytes_written;
    printf("Закодовано %zu байтів\n", message_length);
    
    // Вивід шістнадцяткового дампу закодованих даних
    printf("Закодовані дані: ");
    for (size_t i = 0; i < message_length; i++) {
        printf("%02x ", buffer[i]);
    }
    printf("\n");
    
    // --- ДЕКОДУВАННЯ ---
    example_ScalarMessage decoded = example_ScalarMessage_init_zero;
    
    // Створення потоку для декодування
    pb_istream_t istream = pb_istream_from_buffer(buffer, message_length);
    
    // Декодування повідомлення
    if (!pb_decode(&istream, example_ScalarMessage_fields, &decoded)) {
        printf("Помилка декодування: %s\n", PB_GET_ERROR(&istream));
        return 1;
    }
    
    // Вивід декодованих значень
    printf("Декодовані значення:\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;
}

Команда компіляції

Скомпілюйте приклад з nanopb. NanoPB зазвичай використовується шляхом безпосереднього включення вихідних файлів у ваш проєкт:

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

Примітка: Вихідні файли NanoPB (pb_common.c, pb_encode.c, pb_decode.c) потрібно компілювати безпосередньо з вашим проєктом. Їх можна отримати з репозиторію NanoPB на GitHub.

Скрипт тестування на Python

Щоб перевірити кодування, ви можете використати бібліотеку protobuf для Python:

test_scalars.py
import scalars_pb2

# Читання бінарних даних
with open('encoded.bin', 'rb') as f:
    data = f.read()

# Декодування
msg = scalars_pb2.ScalarMessage()
msg.ParseFromString(data)

print("Декодовані 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}")

Спочатку скомпілюйте визначення protobuf для Python:

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

Потім змініть приклад на C++, щоб зберегти закодовані дані у файл:

save_encoded_scalars.cpp
// Після кодування додайте це:
FILE *f = fopen("encoded.bin", "wb");
fwrite(buffer, 1, message_length, f);
fclose(f);

Ключові моменти

Очікуваний вивід

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

Інші публікації про NanoPB


Дивіться схожі статті за категоріями: Embedded, C/C++, Protocol Buffers