背景
RTOS系统,使用protobuf-c-compiler生成的库比较大,为精简代码空间,找到了适合RTOS系统的nanopb
生成proto源码
1 定义一个消息tp.proto
syntax = "proto2";
package tp;
message AuthBlock {
enum METHOD {
AUTH_MD5 = 0;
AUTH_TOKEN = 1;
}
optional METHOD method = 1;
optional bytes pri = 2;
}
message Auth {
optional string name = 1;
optional AuthBlock auth = 2;
}
message AuthAck {
optional int32 result = 1 [default = 0];
}
2 生成源码
protoc --plugin=../generator/protoc-gen-nanopb --nanopb_out=./ tp.proto
生成结构如下:
/* Struct definitions */
typedef struct _tp__AuthAck {
bool has_result;
int32_t result;
/* @@protoc_insertion_point(struct:tp__AuthAck) */
} tp__AuthAck;
typedef struct _tp__AuthBlock {
bool has_method;
tp__AuthBlock__METHOD method;
pb_callback_t pri;
/* @@protoc_insertion_point(struct:tp__AuthBlock) */
} tp__AuthBlock;
typedef struct _tp__Auth {
pb_callback_t name;
bool has_auth;
tp__AuthBlock auth;
/* @@protoc_insertion_point(struct:tp__Auth) */
} tp__Auth;
pb_callback_t
:WTF?
3 改善源码中的结构类型
类型为string,repeated,message等消息的,生成的结构类型为pb_callback_t
,对于从protobuf-c转过来的人,使用应该表示不适应,可以这样改造,调整nanopb_generator.py
文件中对于默认类型的转换:
···
class Field:
...
# Decide how the field data will be allocated
if field_options.type == nanopb_pb2.FT_DEFAULT:
if can_be_static:
field_options.type = nanopb_pb2.FT_STATIC
else:
field_options.type = nanopb_pb2.FT_POINTER #change DEFAULT nanopb_pb2.FT_CALLBACK to nanopb_pb2.FT_POINTER
···
重新生成源码:
···
/* Struct definitions /
typedef struct _tp__AuthAck {
bool has_result;
int32_t result;
/ @@protoc_insertion_point(struct:tp__AuthAck) */
} tp__AuthAck;
typedef struct _tp__AuthBlock {
bool has_method;
tp__AuthBlock__METHOD method;
pb_bytes_array_t pri;
/ @@protoc_insertion_point(struct:tp__AuthBlock) */
} tp__AuthBlock;
typedef struct _tp__Auth {
char name;
bool has_auth;
tp__AuthBlock auth;
/ @@protoc_insertion_point(struct:tp__Auth) */
} tp__Auth;
···
虽然还有另一种方式,就是添加对应协议的类型参数,这样也能达到效果。但是目测繁琐所以推荐使用, 新建tp.options
文件:
tp.Auth.name type:FT_POINTER
tp.Auth.auth type:FT_POINTER
...
使用
按照官方示例自己根据需要做序列化和反序列化即可。
网友评论