在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