protobuf-c简介
一、数据类型照
proto类型 | C/C++类型 | proto类型 | C/C++类型 |
---|
double | double | float | float |
int32 | int32 | int64 | int64 |
uint32 | uint32 | uint64 | uint64 |
sint32 | int32 | sint64 | int64 |
fixed32 | uint32 | fixed64 | uint64 |
sfixed32 | int32 | sfixed64 | int64 |
bool | bool | string | string(c++),char*( c ) |
二、proto文件格式与类型
proto syntax="proto2"; #指定proto版本,推荐用2
message ID #消息名称:结构体名称
{
required string id = 1;
}
# 消息结构可嵌套,也可包含其他proto文件,使用其中的消息结构
message talk
{
required ID s_id = 1; #required:该域必须有且仅有一个实例
repeated ID d_id = 2; #repeated:该域可有0至多个实例
required string content = 3;
optional int64 timeout = 4; #optional:该域可有0或1个实例
}
三、生成头文件与源文件指令
protoc-c --c_out=头文件与源文件输出目录 -I proto文件所在目录 proto文件名
四、对应结构
typedef struct _ID ID;
typedef struct _Talk Talk;
struct _ID
{
ProtobufCMessage base;
char *id;
};
struct _Talk
{
ProtobufCMessage base;
ID *s_id;
size_t n_d_id; //对应的repeated域字段名会有一个计数域,填充完实例后需要手动赋值个数,否则序列化域反序列化异常
ID **d_id;
char *content;
protobuf_c_boolean has_timeout;
int64_t timeout;
};
五、常用宏与接口
//必须初始化实例,否则序列化异常
//为定义的实例初始化:Talk t = TALK__INIT;
TALK__INIT
//初始化动态分配的实例:Talk t = malloc(sizeof(Talk)); talk_init(t);
void talk__init(Talk *message);
//获取序列化后数据大小,用于为其分配保存序列化后数据的空间
size_t talk__get_packed_size(const Talk *message);
//将结构序列化进缓存空间
size_t talk__pack(const Talk *message,uint8_t *out);
//反序列化
Talk * talk__unpack(ProtobufCAllocator *allocator,size_t len,const uint8_t *data);
//释放反序列化实例占用空间
void talk__free_unpacked(Talk *message,ProtobufCAllocator *allocator);
Talk t = TALK__INIT;
size_t len = talk_get_packed_size(&t);
//填充结构数据域
//...
//...
char *buf = (char*)malloc(len);
talk__pack(&t, (uint8_t*)buf);
Talk *tt = talk__unpack(NULL, len, (uint8_t *)buf);
//处理业务
//...
//...
talk__free_unpacked(tt, NULL);
六、demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "msg.pb-c.h"
int main(int argc, char **argv)
{
char *buf = NULL;
Talk t = TALK__INIT;
Talk *talk = NULL;
int num = 2;
size_t len = 0;
ID* s_id = (ID*)malloc(sizeof(ID));
ID** d_id = (ID**)malloc(sizeof(ID*) * num);
t.content = (char*)malloc(100);
memset(t.content, 0x00, 100);
strcpy(t.content, "Hello, Protobuf-c.");
id__init(s_id);
s_id->id = (char*)malloc(7);
memset(s_id->id, 0x00, 7);
strcpy(s_id->id, "1234584");
t.s_id = s_id;
d_id[0] = (ID*)malloc(sizeof(ID));
d_id[1] = (ID*)malloc(sizeof(ID));
id__init(d_id[0]);
id__init(d_id[1]);
d_id[0]->id = (char*)malloc(7);
d_id[1]->id = (char*)malloc(7);
memset(d_id[0]->id, 0x00, 7);
memset(d_id[1]->id, 0x00, 7);
strcpy(d_id[0]->id, "1234585");
strcpy(d_id[1]->id, "1234586");
t.d_id = d_id;
t.n_d_id = num;
len = talk__get_packed_size(&t);
buf = (char*)malloc(len);
talk__pack(&t, (uint8_t*)buf);
num = 0;
talk = talk__unpack(NULL, len, (uint8_t*)buf);
printf("s_id: %s\n", talk->s_id->id);
printf("d_id: \t");
for(num = 0; num < talk->n_d_id; ++num)
{
printf("%s\t", talk->d_id[num]->id);
}
printf("\nContent: %s\n", talk->content);
talk__free_unpacked(talk, NULL);
free(buf);
return 0;
}