1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dianqi0901zc-nanopb_test

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
README.md 9.3 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 06.06.2025 06:11 c28ab49
сообщение TestMessage {
  необходимое int32 id = 1;
  необязательное string name = 2;
}

Пример запуска теста

./nanopb_test --test_data=test_data.pb --verbose

Проверка результатов

После запуска тестов nanopb_test, результаты будут отображены в консоли. Убедитесь, что все тесты прошли успешно и нет ошибок.


Эта инструкция предназначена для помощи в использовании nanopb_test для тестирования библиотеки nanopb.

Пролог

В недавно разработанном проекте по работе с Bluetooth, было обнаружено, что на некоторых платформах объем доступной памяти очень мал. Использование protobuf-c для сериализации данных может быть ограничено из-за недостатка памяти.

Для языка C в среде embedded Nanopb является хорошим выбором для сериализации данных. Использование Nanopb также является относительно простым. Nanopb имеет унифицированный интерфейс для кодирования и декодирования данных (функции pb_encode и pb_decode). В отличие от этого, protobuf-c генерирует отдельные интерфейсы для кодирования и декодирования для каждого сообщения.# Скачивание и установка Nanopb Ссылка для скачивания: https://jpa.kapsi.fi/nanopb/download/ Я скачал версию для Linux: nanopb-0.3.9.2-linux-x86.tar.gz Скриншот скачанного файла После того, как вы скачали и распаковали архив, следующие файлы будут использоваться для кодирования и декодирования данных: pb_common.c, pb_common.h, pb_decode.c, pb_decode.h, pb_encode.c, pb_encode.h, pb.h. Эти файлы следует поместить на платформу, на которой вы планируете использовать библиотеку.Скриншот распакованного архива

Определение .proto файла

  • Я определил произвольный файл UserInformation.proto.
syntax = "proto3";
option optimize_for = LITE_RUNTIME;

enum UserStatus {
	UNKNOWN = 0;
	IDLE = 1;
	BUSY = 2;
}
```сообщение UserInformation {
 	string name = 1;
 	uint32 age = 2;	
 	string phone = 3;
 	UserStatus stat = 4;
 	string email = 5;
 }
  • В .proto файле опция optimize_for: опция optimize_for = LITE_RUNTIME; optimize_for является опцией на уровне файла. Protocol Buffer определяет три уровня оптимизации: SPEED/CODE_SIZE/LITE_RUNTIME. По умолчанию используется SPEED. SPEED: указывает на высокую производительность выполнения сгенерированного кода, но при этом компилируемый код будет занимать больше места. CODE_SIZE: противоположно SPEED, код выполняется медленнее, но компилируемый код занимает меньше места. Обычно используется на платформах с ограниченными ресурсами, таких как мобильные устройства. LITE_RUNTIME: сгенерированный код выполняется быстро, при этом занимает очень мало места. Это достигается за счёт отказа от функции рефлексии, предоставляемой Protocol Buffer. Поэтому при линковке Protocol Buffer в C++ используется только libprotobuf-lite, а не libprotobuf. В Java достаточно включить protobuf-java-2.4.1-lite.jar, а не protobuf-java-2.4.1.jar.

    Примечание: для опции LITE_MESSAGE, все сгенерированные сообщения будут наследовать от MessageLite, а не от Message.

  • Важно: компилятор Nanopb не поддерживает динамическое определение типа string, в то время как Protobuf-c компилирует его как char *. Однако Nanopb всегда компилирует его как массив типа char. Поэтому здесь необходимо определить UserInformation.options:
// *******************************
// *** UserInformation options ***
// *******************************
//
UserInformation.name max_size:20
UserInformation.phone max_size:16
UserInformation.email max_size:30
```# Компиляция .proto файла
- Команда для компиляции C кода: `. /generator-bin/protoc --nanopb_out=. /UserInformation.proto`
! [Здесь должна быть картинка](https://img-blog.csdnimg.cn/20190130162917628.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1pIT05HQ0FJMDkwMQ==,size_16,color_FFFFFF,t_70)
- Команда для компиляции C++ кода: `. /generator-bin/protoc --cpp_out=. /UserInformation.proto`
! [Здесь должна быть картинка](https://img-blog.csdnimg.cn/20190130163147412.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1pIT05HQ0FJMDkwMQ==,size_16,color_FFFFFF,t_70)

# Тестовый пример кода
Упаковка данных пользователя, основные 4 шага:
- Определение и инициализация переменной `UserInformation userInfo`;
- Присвоение значений переменной `userInfo`;
- Использование `pb_ostream_from_buffer` для создания `pb_ostream_t`, который содержит адрес буфера для кодирования;
- Использование `pb_encode` для кодирования.
```c
static int pack_user_data(uint8_t *buffer)
{
   // Инициализация структуры UserInformation;
   UserInformation userInfo = UserInformation_init_zero;
   // Инициализация буфера
   memset(buffer, 0, DATA_BUFFER_SIZE);
}
``````c
strcpy(userInfo.name, "Benjamin");
userInfo.age = 18; 
strcpy(userInfo.phone, "0755-12345678");
userInfo.stat = UserStatus_IDLE;
strcpy(userInfo.email, "ZhangSan@123.com");

// Кодирование данных userInfo
pb_ostream_t enc_stream;
enc_stream = pb_ostream_from_buffer(buffer, DATA_BUFFER_SIZE);
if (!pb_encode(&enc_stream, UserInformation_fields, &userInfo))
{
   // Произошла ошибка кодирования
   printf("pb encode error in %s [%s]\n", __func__, PB_GET_ERROR(&enc_stream));
   return -1;
}

return enc_stream.bytes_written;
}

Распаковка данных пользователя включает в себя три основных шага:

  • Определение и инициализация переменной UserInformation userInfo;
  • Использование pb_istream_from_buffer для создания pb_istream_t, содержащего адрес буфера для декодирования;
  • Использование pb_decode для декодирования.
static int unpack_user_data(const uint8_t *buffer, size_t len)
{
    UserInformation userInfo;

    // Декодирование данных userInfo
	pb_istream_t dec_stream;
	dec_stream = pb_istream_from_buffer(buffer, len);
	if (!pb_decode(&dec_stream, UserInformation_fields, &userInfo))
	{
		printf("pb decode error in %s\n", __func__);
		return -1;
	}

    printf("Распаковка: %s %d %s %s\n", userInfo.name, userInfo.age, userInfo.phone, userInfo.email);

    return 0;
}

Основная функция main для вызова

int main()
{
    uint8_t buffer[DATA_BUFFER_SIZE];

    int length = pack_user_data(buffer);
    if(length < 0){
        printf("main: pack_user_data failed!!!\n");
        return -1;
    }
    printf("Длина данных пользователя: %d\n", length);
    unpack_user_data(buffer, length);
	
	return 0;
}

Результат выполнения программы: Здесь должна быть картинка

Полный код проекта

адрес на gitee: https://gitee.com/dianqi0901zc/nanopb_test

Ссылка на блог: https://blog.csdn.net/ZHONGCAI0901/article/details/86705381


Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/dianqi0901zc-nanopb_test.git
git@api.gitlife.ru:oschina-mirror/dianqi0901zc-nanopb_test.git
oschina-mirror
dianqi0901zc-nanopb_test
dianqi0901zc-nanopb_test
master