在nanopb中,string类型在生成c语言文件的时候,会有两种结构,一种是指定了最大长度的,一种是没有指定最大长度.指定了最大长度的string,会生成char[] 数组类型,没有指定最大长度的,会生成pb_callback_t类型.具体的可以参照nanopb文档
pb_callback_t 是一个结构体,有两个成员变量,一个是回调函数指针,这个回调函数是一个union,在编码的时候,需要赋值encode函数,解码的时候赋值decode,如果不赋值,则该属性值会忽略.
另外一个变量是arg,这是一个指针,会在回调函数中作为最后一个参数传递给回调函数.
typedef struct pb_callback_s pb_callback_t; struct pb_callback_s { #ifdef PB_OLD_CALLBACK_STYLE /* Deprecated since nanopb-0.2.1 */ union { bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); } funcs; #else /* New function signature, which allows modifying arg contents in callback. */ union { bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); } funcs; #endif /* Free arg for use by callback */ void *arg; };
调用方法如下例:
// // main.c // Test // // Created by Wangchun on 2018/2/11. // Copyright © 2018年 Benzhuo. All rights reserved. // #include <stdio.h> #include "pb.h" #include "message.pb.h" #include "pb_common.h" #include "pb_encode.h" #include "pb_decode.h" /** 编码的回调函数 **/ bool write_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { char *str = *arg; if (!pb_encode_tag_for_field(stream, field)) return false; return pb_encode_string(stream, (uint8_t*)str, strlen(str)); } /** 解码回调函数 **/ bool read_ints(pb_istream_t *stream, const pb_field_t *field, void **arg) { int i=0; char* tmp = *arg; while (stream->bytes_left) { uint64_t value; if (!pb_decode_varint(stream, &value)) return false; *(tmp+i)=value; i++; } return true; } int main(int argc, const char * argv[]) { // insert code here... printf("Hello, World!\n"); printf("hello world!!!!!\n"); uint8_t buffer[128]; size_t message_length; bool status; { SigninReq sign = SigninReq_init_zero; sign.lockId.funcs.encode = write_string; sign.lockId.arg = &"hahaha"; sign.sid=12345; pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); status = pb_encode(&stream, SigninReq_fields, &sign); message_length = stream.bytes_written; /* Then just check for any errors.. */ if (!status) { printf("Encoding failed: %s\n", PB_GET_ERROR(&stream)); return 1; } } { /* Allocate space for the decoded message. */ SigninReq message = SigninReq_init_zero; message.lockId.funcs.decode = read_ints; char tmp[128]={0}; message.lockId.arg = &tmp; /* Create a stream that reads from the buffer. */ pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); /* Now we are ready to decode the message. */ status = pb_decode(&stream, SigninReq_fields