Протокол буфера nanopb Сериализация строки и ошибка декодирования utf-8 символов - PullRequest
0 голосов
/ 23 октября 2019

В настоящее время я пытаюсь сериализовать строку, используя nanopb, и расшифровываю сообщение в python / java. У меня нет проблем, и я могу сериализовать и десериализовать. Но когда дело доходит до строки, я получаю одну и ту же ошибку: кодек «utf-8» не может декодировать байт 0xff в позиции 2: кодек «utf-8» не может декодировать байт 0xff в позиции 2: недопустимый начальный байт вполе:

Я подумал, что это может быть проблема с декодированием Python, поэтому я изменил: with open('FileSerialized.bin', 'rb') as f: на

with open('FileSerialized.bin', encode='utf-8') as f:

Я попытался с парсером в Java, и он выдал ту же ошибку. Поэтому я предполагаю, что проблема в том, как я кодирую сообщение в C. Я делаю следующее:

После того, как nanopb обеспечил преобразование .proto:

typedef struct _ProtoExample {
    int32_t Value1;  //this is deserialized correctly
    char Value2[6]; //here is where I have trouble
}

И япопытался заполнить массив char, выполнив следующее:

pb_ostream_t stream = pb_ostream_from_buffer( buffer, BUFFER_SIZE );
ProtoExample Message;
Message.Value1= S_generalConfig_s.EntityType;
Message.Value2[0] = 'a';

pb_encode( &stream, ProtoExample _fields, &Message);

После попытки декодирования я обнаружил ошибку при попытке прочитать Value2.

1 Ответ

1 голос
/ 23 октября 2019
ProtoExample Message;
Message.Value1= S_generalConfig_s.EntityType;
Message.Value2[0] = 'a';

Хорошая идея инициализировать структуры сообщений. В противном случае, если вы забудете инициализировать какое-либо поле, оно будет содержать случайные данные. Поэтому измените первую строку на:

ProtoExample Message = ProtoExample_init_default;

Здесь ProtoExample_init_default - это макрос инициализации, сгенерированный nanopb, который будет содержать любые значения по умолчанию, определенные в файле .proto. Вы также можете использовать ProtoExample_init_zero для инициализации пустых значений.

Фактическая проблема заключается в том, что ваша строка не определена. В Си строки должны заканчиваться символом '\ 0', чтобы быть действительными. Поэтому вам нужно добавить:

Message.Value2[1] = '\0';

, чтобы установить терминатор после вашего единственного символа. Если вы добавите инициализацию по умолчанию, она установит все байты в ноль. В этом случае это отчасти избыточно, но, как правило, это хорошая практика программирования для обеспечения завершения строк.

...