nanopb中的enn编码和解码问题



最近开始探索nanopb-如果我的问题听起来很无聊,请道歉。当我修改nanopb的简单示例时,我在分配和检索字符串和整数时遇到了一些问题。让我在提问前给出我的步骤-

  1. 我定义了simple.proto文件
message Device{
optional string devid =1; 
optional string mac = 2; 
optional string cpu=3 [default = "x86"] ; 
optional bool isSecured=4;
optional int32 uptime = 5 [default = 1234];
}
  1. 也定义了simple.option
Device.devid max_size:64
Device.cpu max_size:64

然后我像往常一样编译:protocol-osimple.pb simple.proto

  1. 这是我的代码:

3a(当字符串是pb_callback_t类型时,使用与"如何对其进行编码"中相同的字符串编码-解码实用程序函数

//string encode decode to pb
bool encode_string(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
const char* str = (const char*)(*arg);
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
bool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint8_t buffer[1024] = {0};
/* We could read block-by-block to avoid the large buffer... */
if (stream->bytes_left > sizeof(buffer) - 1)
return false;
if (!pb_read(stream, buffer, stream->bytes_left))
return false;
/* Print the string, in format comparable with protoc --decode.
* Format comes from the arg defined in main().     */
printf((char*)*arg, buffer);
return true;
}

3b(这是我基于示例的simple.c的主要代码片段-

/* This is the buffer where we will store our message. */
uint8_t buffer[128];
size_t message_length;
bool status;
/* Encode our message */
{
/* Allocate space on the stack to store the message data, check out the contents of simple.pb.h
* good to always initialize your structures so that no garbage data from RAM in there.   */
//Device message = Device_init_zero;   //init zero   for empty
Device message = Device_init_default;  //init default for default
/* Create a stream that will write to our buffer. */
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
/* Fill in the data */
message.devid.arg = "device1";
message.devid.funcs.encode = &encode_string;

//strcpy(message.devid,"device1");  // no easier way like this ?
message.isSecured = true;   // should be 1 if printed with %d
message.uptime=9876;        // should change, why it is not working ?
/* Now we are ready to encode the message! */
// encode stream to buffer , also get the buffer length
status = pb_encode(&stream, Device_fields, &message);
message_length = stream.bytes_written;
/* Then just check for any errors.. */
if (!status)
{
printf("Encoding failed: %sn", PB_GET_ERROR(&stream));
return 1;
}
}
/* Now we could transmit the message over network, store it in a file etc.   */
/* just decode it immediately. */
{
/* Allocate space for the decoded message. */
Device message = Device_init_zero;
/* Create a stream that reads from the buffer. */
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
message.devid.funcs.decode = &print_string;
message.devid.arg = "before decode Device - devid: %s n"; //works here
message.cpu.funcs.decode = &print_string;
message.cpu.arg = "before decode Device -cpu: %s n";   //where in op?
printf("before decode isSecured %dn",message.isSecured);  // doesn't work

printf("before decode uptime %dn",message.uptime); //doesn't work
/* Now ready to decode the message. */
// decode  stream buffer into message
status = pb_decode(&stream, Device_fields, &message);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %sn", PB_GET_ERROR(&stream));
return 1;
}
/* Print the data contained in the message. */

message.devid.funcs.decode = &print_string;
message.devid.arg = "after decode Devic - devid: %s n";  // doesn't work here
printf(" after decode isSecured %dn",message.isSecured);  // prints default 0        
printf(" after decode uptime %dn",(int)message.uptime);   //prints default assigned in proto
}
  1. 构建和运行后的输出:
$ ./simple
before decode isSecured 0
before decode uptime 0
before decode Device - devid: device1
after decode isSecured 0
after decode uptime 1234

我的查询(还添加了代码中的内联注释(:

  1. 在原来的simple.c message.rucky_number=13赋值有效,但在这里message.uptime赋值无效,它取默认值。类似地,将布尔值分配给message.isSecured也不起作用。请告诉我哪里是我的错
  2. 我在pb_encode之前使用了Device_init_default,因为有些具有默认值,在pb_decode调用之前使用Device_init_zero,因为它将在解码后填充。我的方法正确吗
  3. 除了encode_string和decode_string util之外,还有什么更简单的方法可以使用strcpy分配字符串值,并通过printf("%s",strvar(以C方式打印它吗
  4. 字符串仅在pb_decode调用之前打印,但正常运行时间默认值在pb_decode调用之后打印。此外,布尔值赋值也不起作用。为什么?我犯了什么错
  5. 我在中看到了编码字符串和int函数https://github.com/nanopb/nanopb/blob/master/tests/callbacks/encode_callbacks.c如何对浮点和布尔值进行编码和解码

感谢

  1. 在原来的simple.c message.rucky_number=13赋值有效,但在这里message.uptime赋值无效,它取默认值。类似地,将布尔值分配给message.isSecured也不起作用。请告诉我哪里是我的错

如果查看生成的.pb.h文件,您会发现每个可选字段都有一个布尔has_field。您还必须将其设置为true,以表示字段存在。

  1. 我在pb_encode之前使用Device_init_default,因为有些具有默认值,在pb_decode调用之前使用Device_init_zero,因为它将在解码后填充。我的方法正确吗

没关系。

  1. 除了encode_string和decode_string util之外,还有什么更简单的方法可以使用strcpy分配字符串值,并通过printf("%s",strvar(以C方式打印它吗

因为您已经为字符串字段设置了max_size,所以应该将它们生成为char数组,而不是回调。您可以尝试传递-v开关,如:../generator/nanopb_generator.py -v simple.pb,以查看更详细的消息,这些消息可以指出该选项不适用的原因。也许文件名不正确,或者消息名不正确。

字符串仅在pb_decode调用之前打印,但正常运行时间默认值在pb_decode调用之后打印。此外,布尔值赋值也不起作用。为什么?我犯了什么错?

我在中看到了编码字符串和int函数https://github.com/nanopb/nanopb/blob/master/tests/callbacks/encode_callbacks.c如何对浮点和布尔值进行编码和解码?

通常情况下,您不必求助于回调。但是,如果您决定需要它们,则可以使用pb_encode_varint()对布尔值进行编码,并使用pb_encode_fixed32()对浮点值进行编码。对于研究回调,protobuf编码文档和这个测试用例可能会有所帮助。


您可能会发现network_server示例对研究很有用。

此外,当每个帖子只有一个问题时,堆栈溢出格式效果最好。这样,问题和答案就保持了重点,易于理解。

最新更新