nanopb关于string类型的处理


在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, &message); /* Check for errors... */ if (!status) { // printf("Decoding failed: %s\n", PB_GET_ERROR(&stream)); return 1; } /* Print the data contained in the message. */ printf("Your sid = %d!, lockId=%s\n", message.sid,tmp); } return 0; } 

这种方式使用起来比较复杂,一般情况下,我们的长度都不会太长,这样我们可以设定string的最大长度,就可以用char[]数组的方式来处理了.这样使用起来比较简单.设定最大长度的方式有几种,可以参照网站上来做,我用的是options配置文件的方式来生成.

首先创建.proto文件

syntax = "proto3";

message SigninReq {
    int32 sid = 1;// session id ,int型随机数
    string uid = 2; //userId
}

再创建一个.options文件

# lock.options
SigninReq.uid   max_size:16 

protoc生成中间文件的方式不变(参见上一篇文章),在执行nanopb_generator.py的时候,添加上参数 -f lock.options, 这样就可以生成char[]数组类型了.为了方便,将上篇文章中的shell脚本进行了修改.去掉了编译多个pb文件生成c文件功能,一次只编译一个pb文件.

#!/bin/sh
nanodir="nanopb的home目录"
nanopy=$nanodir"/generator/nanopb_generator.py"
file1=$nanodir"/pb_common.c"
file2=$nanodir"/pb_common.h"
file3=$nanodir"/pb_decode.c"
file4=$nanodir"/pb_decode.h"
file5=$nanodir"/pb_encode.c"
file6=$nanodir"/pb_encode.h"
file7=$nanodir"/pb.h"
srcdir=`pwd`
mkdir $srcdir"/ccode"
dir=$srcdir"/ccode"
params=""
isP=0
pbfile=""
for i in "$@"; do
    if [[ $i == "-"* ]];then 
        params=$params" "$i
        isP=1
    elif [ $isP -eq 1 ];then
       params=$params" "$i
       isP=0
    else
       pbfile=$i
    fi
done
echo "pbfile:"$pbfile
echo "params:"$params
python $nanopy $pbfile $params
mv $srcdir"/"$pbfile".c" $dir
mv $srcdir"/"$pbfile".h" $dir
cp $file1 $dir
cp $file2 $dir
cp $file3 $dir
cp $file4 $dir
cp $file5 $dir
cp $file6 $dir
cp $file7 $dir


作者:雾里布谷鸟
链接:https://www.jianshu.com/p/cad578f48e0a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM