问题描述
最近开始研究nanopb-如果我的问题听起来很傻,就道歉。修改nanopb的简单示例时,我在分配和检索字符串和整数时遇到一些问题。让我先回答我的问题-
- 我定义了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];
}
- 还定义了simple.option
Device.devid max_size:64
Device.cpu max_size:64
然后我像往常一样编译:protoc -osimple.pb simple.proto
- 这是我的代码:
3a)使用与How to encode a string when it is a pb_callback_t type
中相同的字符串编码解码实用程序功能//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: %s\n",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 %d\n",message.isSecured); // doesn't work
printf("before decode uptime %d\n",message.uptime); //doesn't work
/* Now ready to decode the message. */
// decode stream buffer into message
status = pb_decode(&stream,&message);
/* Check for errors... */
if (!status)
{
printf("Decoding Failed: %s\n",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 %d\n",message.isSecured); // prints default 0
printf(" after decode uptime %d\n",(int)message.uptime); //prints default assigned in proto
}
- 构建并运行后的输出:
$ ./simple
before decode isSecured 0
before decode uptime 0
before decode Device - devid: device1
after decode isSecured 0
after decode uptime 1234
- 在原始的simple.c中,message.lucky_number = 13分配有效,但这里的message.uptime分配不起作用,它采用默认值。同样,将布尔值分配给message.isSecured无法正常工作。请告诉我我的错在哪里。
- 我在pb_encode之前使用Device_init_default,因为有些具有默认值,在pb_decode调用之前使用Device_init_zero,因为它将在解码后填充。我的方法正确吗?
- 除了encode_string和decode_string util之外,还有没有更简单的方法使用strcpy分配字符串值并通过printf(“%s”,strvar)以C方式打印它?
- 仅在调用pb_decode之前打印字符串,但是在调用pb_decode之后打印正常运行时间默认值。布尔值分配也不起作用。为什么呢我怎么了?
- 我在https://github.com/nanopb/nanopb/blob/master/tests/callbacks/encode_callbacks.c中看到了编码字符串和int函数 如何对float和boolean进行编码和解码?
感谢您的期待
解决方法
- 在原始的simple.c中,message.lucky_number = 13分配有效,但这里的message.uptime分配不起作用,它采用默认值。同样,将布尔值分配给message.isSecured无法正常工作。请告诉我我的错在哪里。
如果查看生成的.pb.h
文件,您会发现每个可选字段都有一个布尔值has_field
。您还必须将其设置为true,以表示该字段存在。
- 我在pb_encode之前使用Device_init_default,因为有些具有默认值,在pb_decode调用之前使用Device_init_zero,因为它将在解码后填充。我的方法正确吗?
很好。
- 除了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之后打印正常运行时间默认值。布尔值分配也不起作用。为什么呢我怎么了?
我在https://github.com/nanopb/nanopb/blob/master/tests/callbacks/encode_callbacks.c中看到了编码字符串和int函数的方法如何编码和解码float和boolean?
好吧,通常您不必诉诸回调。但是,如果您决定需要它们,则可以使用pb_encode_varint()
编码布尔值,并使用pb_encode_fixed32()
浮动值。对于研究回调,protobuf encoding documentation和this test case可能会有所帮助。
您可能会发现network_server
示例对学习很有帮助。
此外,当每个帖子只有一个问题时,堆栈溢出格式最有效。这样,问题和答案就可以保持重点突出并且易于理解。