介紹
Protocol Buffers,是Google公司開發(fā)的一種數(shù)據(jù)描述語言,類似于XML能夠?qū)⒔Y(jié)構(gòu)化數(shù)據(jù)序列化,可用于數(shù)據(jù)存儲、通信協(xié)議等方面。它不依賴于語言和平臺并且可擴(kuò)展性極強(qiáng)。
同XML相比,Protocol buffers在序列化結(jié)構(gòu)化數(shù)據(jù)方面有許多優(yōu)點:
1. 更簡單
2. 數(shù)據(jù)描述文件只需原來的1/10至1/3
3. 解析速度是原來的20倍至100倍
4. 減少了二義性
5. 生成了更容易在編程中使用的數(shù)據(jù)訪問
6.支持多種編程語言
(轉(zhuǎn)自百度百科)
- 完整代碼放到我的github下了
安裝
這里我使用的是 protobuf-c,在安裝 protobuf-c 之前需要安裝 protobuf 。
安裝protobuf
首先安裝依賴 sudo apt-get install autoconf automake libtool curl make g++ unzip
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
./autogen.sh
./configure
make
make check # make check 失敗的話沒關(guān)系,繼續(xù)下面的安裝
sudo make install
sudo ldconfig
安裝protobuf-c
首先安裝依賴sudo apt-get install pkg-config pkgconf
git clone https://github.com/protobuf-c/protobuf-c.git
./autogen.sh && ./configure && make && make install
到這里就已經(jīng)安裝好 protobuf 和 protobuf-c
使用protobuf-c
編輯文件student.proto 這里用的是proto2(建議新手直接上 proto3)
這里以 student 為例子
syntax = "proto2";
message Student {
optional string name = 1;
}
命令protoc --c_out=. student.proto
生成.c和.h文件 student.pb-c.c student.pb-c.h
不要太關(guān)注下面的兩個文件
- 下面是生成的
student.pb-c.h
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
/* Generated from: student.proto */
#ifndef PROTOBUF_C_student_2eproto__INCLUDED
#define PROTOBUF_C_student_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 1003003 < 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 _Student Student;
/* --- enums --- */
/* --- messages --- */
struct _Student
{
ProtobufCMessage base;
char *name;
};
#define STUDENT__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&student__descriptor) \
, NULL }
/* Student methods */
void student__init
(Student *message);
size_t student__get_packed_size
(const Student *message);
size_t student__pack
(const Student *message,
uint8_t *out);
size_t student__pack_to_buffer
(const Student *message,
ProtobufCBuffer *buffer);
Student *
student__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void student__free_unpacked
(Student *message,
ProtobufCAllocator *allocator);
/* --- per-message closures --- */
typedef void (*Student_Closure)
(const Student *message,
void *closure_data);
/* --- services --- */
/* --- descriptors --- */
extern const ProtobufCMessageDescriptor student__descriptor;
PROTOBUF_C__END_DECLS
#endif /* PROTOBUF_C_student_2eproto__INCLUDED */
- 下面是生成的
student.pb-c.c
// student.pb-c.c
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
/* Generated from: student.proto */
/* Do not generate deprecated warnings for self */
#ifndef PROTOBUF_C__NO_DEPRECATED
#define PROTOBUF_C__NO_DEPRECATED
#endif
#include "student.pb-c.h"
void student__init
(Student *message)
{
static const Student init_value = STUDENT__INIT;
*message = init_value;
}
size_t student__get_packed_size
(const Student *message)
{
assert(message->base.descriptor == &student__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t student__pack
(const Student *message,
uint8_t *out)
{
assert(message->base.descriptor == &student__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t student__pack_to_buffer
(const Student *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &student__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Student *
student__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (Student *)
protobuf_c_message_unpack (&student__descriptor,
allocator, len, data);
}
void student__free_unpacked
(Student *message,
ProtobufCAllocator *allocator)
{
if(!message)
return;
assert(message->base.descriptor == &student__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
static const ProtobufCFieldDescriptor student__field_descriptors[1] =
{
{
"name",
1,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_STRING,
0, /* quantifier_offset */
offsetof(Student, name),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned student__field_indices_by_name[] = {
0, /* field[0] = name */
};
static const ProtobufCIntRange student__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor student__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"Student",
"Student",
"Student",
"",
sizeof(Student),
1,
student__field_descriptors,
student__field_indices_by_name,
1, student__number_ranges,
(ProtobufCMessageInit) student__init,
NULL,NULL,NULL /* reserved[123] */
};
在代碼里使用
編輯文件 student.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "student.pb-c.h"
#define NAME_LEN 32
int main() {
Student stu = STUDENT__INIT; // 初始化
void *buf = NULL;
unsigned int len;
Student *msg = NULL;
stu.name = (char*)malloc(NAME_LEN);
stu.name = "test";
len = student__get_packed_size(&stu); // 算出大小
printf("size of Student info : %u\n", len);
buf = malloc(len);
student__pack(&stu, buf); // 打包
msg = student__unpack(NULL, len, buf); // 解包
printf("msg name : %s\n", msg->name);
student__free_unpacked(msg, NULL); // 釋放空間
free(buf);
return 0;
}
編譯
編譯 gcc student.c student.pb-c.c -o student -lprotobuf-c
需要連接 protobuf-c 庫
輸出:
size of Student info : 6
msg name : test
2020.3.2 16:40 廣州