Протокол Buffer nanopb Строка сериализации и ошибка декодирования Символ UTF-8

В настоящее время я пытаюсь сериализовать строку с помощью 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.


person Asan    schedule 23.10.2019    source источник


Ответы (1)


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 для инициализации пустыми значениями.

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

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

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

person jpa    schedule 23.10.2019