1、前言

项目中用到protobuf-c进行数据序列化,好处在于后期程序扩展性非常好,只需要改动proto的定义就可以保持兼容,非常的灵活方便。关于protobuf-c的详细介绍可以参考google官方文档。https://code.google.com/p/protobuf-c/。在此简单的介绍一下基本功能。proto文件格式如下所示:

message AMessage
{
requried int32 a = ; //a必须出现
optional string b = ; //b是可选的
repeated int32 c = ; //c是数组
}

字段规则类型:

required:表示后面的数据是必须的。

optional:表示后面数据是可选的。

repeated:表示后面的数据是一个数组。

标量数值类型

.proto类型

Java 类型

C++类型

备注

double

double

double

float

float

float

int32

int

int32

使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint32。

int64

long

int64

使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint64。

uint32

int[1]

uint32

Uses variable-length encoding.

uint64

long[1]uint64Uses variable-length encoding.

sint32

int

int32

使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。

sint64

long

int64

使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。

fixed32

int[1]

uint32

总是4个字节。如果数值总是比总是比2大的话,这个类型会比uint32高效。

fixed64

long[1]

uint64

总是8个字节。如果数值总是比总是比2大的话,这个类型会比uint64高效。

sfixed32

int

int32

总是4个字节。

sfixed64

long

int64

总是8个字节。

bool

boolean

bool

string

String

string

一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。

bytes

ByteString

string

可能包含任意顺序的字节数据。

2、测试程序

  编写一个学生信息的proto,proto文件内容如下所示:

 message Student
{
required string id = ;
required string name = ;
required string gender = ;
required int32 age = ;
required string object = ;
required string home_address = ;
required string phone = ;
}

编译命令: protoc-c --c_cout=.  student.proto

生成student.pb-c.c 和 student.pb-c.h两个文件。student.pb-c.h文件内容如下所示:

 /* Generated by the protocol buffer compiler.  DO NOT EDIT! */

 #ifndef PROTOBUF_C_student_2eproto__INCLUDED
#define PROTOBUF_C_student_2eproto__INCLUDED #include <google/protobuf-c/protobuf-c.h> PROTOBUF_C_BEGIN_DECLS typedef struct _Student Student; /* --- enums --- */ /* --- messages --- */ struct _Student
{
ProtobufCMessage base;
char *id;
char *name;
char *gender;
int32_t age;
char *object;
char *home_address;
char *phone;
};
#define STUDENT__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&student__descriptor) \
, NULL, NULL, NULL, , NULL, NULL, 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_student_2eproto__INCLUDED */

测试proto程序如下所示:

 #include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "student.pb-c.h" #define ID_LEN 11
#define NAME_LEN 32
#define GENDER_LEN 10
#define OBJECT_LEN 20
#define HOME_ADDR_LEN 96
#define PHONE_LEN 12 static int malloc_student_info(Student *stu)
{
stu->id = (char*)malloc(ID_LEN);
if (!stu->id)
{
goto FAILED;
}
stu->name = (char*)malloc(NAME_LEN);
if (!stu->name)
{
goto FAILED;
}
stu->gender = (char*)malloc(GENDER_LEN);
if (!stu->gender)
{
goto FAILED;
}
stu->object = (char*)malloc(OBJECT_LEN);
if (!stu->object)
{
goto FAILED;
}
stu->home_address = (char*)malloc(HOME_ADDR_LEN);
if (!stu->home_address)
{
goto FAILED;
}
stu->phone = (char*)malloc(PHONE_LEN);
if (!stu->phone)
{
goto FAILED;
}
return ;
FAILED:
fprintf(stdout, "malloc error.errno:%u,reason:%s\n",
errno, strerror(errno));
return -;
} static void free_student_info(Student *stu)
{
if (stu->id)
{
free(stu->id);
stu->id = NULL;
}
if (stu->name)
{
free(stu->name);
stu->name = NULL;
}
if (stu->gender)
{
free(stu->gender);
stu->gender = NULL;
}
if (stu->object)
{
free(stu->object);
stu->object = NULL;
}
if (stu->home_address)
{
free(stu->home_address);
stu->home_address = NULL;
}
if (stu->phone)
{
free(stu->phone);
stu->phone = NULL;
}
} static void set_student_info(Student *stu)
{
const char *id = "";
const char *name = "Anker";
const char *gender = "male";
const char *object = "computer";
const char *address = "shen zheng";
const char *phone = ""; strncpy(stu->id, id, ID_LEN);
strncpy(stu->name, name, NAME_LEN);
strncpy(stu->gender, gender, GENDER_LEN);
stu->age = ;
strncpy(stu->object, object, OBJECT_LEN);
strncpy(stu->home_address, address, HOME_ADDR_LEN);
strncpy(stu->phone, phone, PHONE_LEN);
} void print_student_info(Student *stu)
{
printf("id: %s\n",stu->id);
printf("name: %s\n",stu->name);
printf("age: %d\n",stu->age);
printf("gender:%s\n",stu->gender);
printf("object: %s\n",stu->object);
printf("home address: %s\n",stu->home_address);
printf("phone: %s\n",stu->phone);
} int main()
{
Student stu = STUDENT__INIT;
void *buf = NULL;
unsigned int len ;
Student *msg = NULL; if (malloc_student_info(&stu) == -) {
exit();
}
set_student_info(&stu); //get student packed size
len = student__get_packed_size(&stu);
printf("size of student info : %u\n",len);
buf = malloc(len);
//put student info pack to buf
student__pack(&stu, buf); //unpack student info from buf
msg = student__unpack(NULL, len, buf);
print_student_info(msg);
//free msg
student__free_unpacked(msg, NULL); free(buf);
free_student_info(&stu); return ;
}

编译命令: gcc student.pb-c.c main.c -o main -lprotobuf-c

测试结果如下所示:

protobuf-c的学习总结-LMLPHP

3、参考网址

http://www.cnblogs.com/dkblog/archive/2012/03/27/2419010.html

https://code.google.com/p/protobuf-c/wiki/Examples

05-11 17:43