protobuf-c 基本使用及样例
Protobuf简介
https://cloud.tencent.com/developer/article/1199069
一、数据类型照
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文件名
头文件
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
/* Generated from: 2.proto */
/* Do not generate deprecated warnings for self */
#ifndef PROTOBUF_C__NO_DEPRECATED
#define PROTOBUF_C__NO_DEPRECATED
#endif
#include "2.pb-c.h"
void id__init
(ID *message)
{
static const ID init_value = ID__INIT;
*message = init_value;
}
size_t id__get_packed_size
(const ID *message)
{
assert(message->base.descriptor == &id__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t id__pack
(const ID *message,
uint8_t *out)
{
assert(message->base.descriptor == &id__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t id__pack_to_buffer
(const ID *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &id__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
ID *
id__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (ID *)
protobuf_c_message_unpack (&id__descriptor,
allocator, len, data);
}
void id__free_unpacked
(ID *message,
ProtobufCAllocator *allocator)
{
if(!message)
return;
assert(message->base.descriptor == &id__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void talk__init
(Talk *message)
{
static const Talk init_value = TALK__INIT;
*message = init_value;
}
size_t talk__get_packed_size
(const Talk *message)
{
assert(message->base.descriptor == &talk__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t talk__pack
(const Talk *message,
uint8_t *out)
{
assert(message->base.descriptor == &talk__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t talk__pack_to_buffer
(const Talk *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &talk__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Talk *
talk__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (Talk *)
protobuf_c_message_unpack (&talk__descriptor,
allocator, len, data);
}
void talk__free_unpacked
(Talk *message,
ProtobufCAllocator *allocator)
{
if(!message)
return;
assert(message->base.descriptor == &talk__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
static const ProtobufCFieldDescriptor id__field_descriptors[1] =
{
{
"id",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_STRING,
0, /* quantifier_offset */
offsetof(ID, id),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned id__field_indices_by_name[] = {
0, /* field[0] = id */
};
static const ProtobufCIntRange id__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor id__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"ID",
"ID",
"ID",
"",
sizeof(ID),
1,
id__field_descriptors,
id__field_indices_by_name,
1, id__number_ranges,
(ProtobufCMessageInit) id__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor talk__field_descriptors[4] =
{
{
"s_id",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(Talk, s_id),
&id__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"d_id",
2,
PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_MESSAGE,
offsetof(Talk, n_d_id),
offsetof(Talk, d_id),
&id__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"content",
3,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_STRING,
0, /* quantifier_offset */
offsetof(Talk, content),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"timeout",
4,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_INT64,
offsetof(Talk, has_timeout),
offsetof(Talk, timeout),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned talk__field_indices_by_name[] = {
2, /* field[2] = content */
1, /* field[1] = d_id */
0, /* field[0] = s_id */
3, /* field[3] = timeout */
};
static const ProtobufCIntRange talk__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 4 }
};
const ProtobufCMessageDescriptor talk__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"talk",
"Talk",
"Talk",
"",
sizeof(Talk),
4,
talk__field_descriptors,
talk__field_indices_by_name,
1, talk__number_ranges,
(ProtobufCMessageInit) talk__init,
NULL,NULL,NULL /* reserved[123] */
};
header
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
/* Generated from: 2.proto */
#ifndef PROTOBUF_C_2_2eproto__INCLUDED
#define PROTOBUF_C_2_2eproto__INCLUDED
#include <protobuf-c/protobuf-c.h>
PROTOBUF_C__BEGIN_DECLS
#if PROTOBUF_C_VERSION_NUMBER < 1000000
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
#elif 1003002 < PROTOBUF_C_MIN_COMPILER_VERSION
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
#endif
typedef struct _ID ID;
typedef struct _Talk Talk;
/* --- enums --- */
/* --- messages --- */
struct _ID
{
ProtobufCMessage base;
char *id;
};
#define ID__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&id__descriptor) \
, NULL }
struct _Talk
{
ProtobufCMessage base;
ID *s_id;
size_t n_d_id;
ID **d_id;
char *content;
protobuf_c_boolean has_timeout;
int64_t timeout;
};
#define TALK__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&talk__descriptor) \
, NULL, 0,NULL, NULL, 0, 0 }
/* ID methods */
void id__init
(ID *message);
size_t id__get_packed_size
(const ID *message);
size_t id__pack
(const ID *message,
uint8_t *out);
size_t id__pack_to_buffer
(const ID *message,
ProtobufCBuffer *buffer);
ID *
id__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void id__free_unpacked
(ID *message,
ProtobufCAllocator *allocator);
/* Talk methods */
void talk__init
(Talk *message);
size_t talk__get_packed_size
(const Talk *message);
size_t talk__pack
(const Talk *message,
uint8_t *out);
size_t talk__pack_to_buffer
(const Talk *message,
ProtobufCBuffer *buffer);
Talk *
talk__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void talk__free_unpacked
(Talk *message,
ProtobufCAllocator *allocator);
/* --- per-message closures --- */
typedef void (*ID_Closure)
(const ID *message,
void *closure_data);
typedef void (*Talk_Closure)
(const Talk *message,
void *closure_data);
/* --- services --- */
/* --- descriptors --- */
extern const ProtobufCMessageDescriptor id__descriptor;
extern const ProtobufCMessageDescriptor talk__descriptor;
PROTOBUF_C__END_DECLS
#endif /* PROTOBUF_C_2_2eproto__INCLUDED */
四、对应结构
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;
};
五、constructor/parser
constructor
size_t pos = 0;
char buf[1024];
char * id = "1234";
char * content = "content";
size_t len = 0;
memset(buf, 0, sizeof(buf));
Talk *talk = (Talk*)buf;
pos += sizeof(*talk);
talk__init(talk);
talk->s_id = buf + pos;
pos += sizeof(*(talk->s_id));
id__init(talk->s_id);
talk->s_id->id = buf + pos;
strcpy(talk->s_id->id, id, strlen(id) + 1);
pos += strlen(id) + 1;
talk->content = buf + pos;
strcpy(talk->s_id->content, content, strlen(content) + 1);
pos += strlen(id) + 1;
/*... do optional filling*/
len = talk__pack(talk, buf);
parser
Talk *unpackedPayload = NULL;
char *msgInfo = NULL;
unpackedPayload = talk__unpack(NULL, msg->len, msg->payload);
msgInfo = protobuf_c_text_to_string((unpackedPayload->base, NULL);
printf("msgInfo %s\n", msgInfo);
/*
unpackedPayload->s_id->id;
unpackedPayload->n_d_id; /*number of */
*/
payload_type__free_unpacked(unpackedPayload);