protobuf-c的学习总结

1、前言

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

message AMessage { requried int32 a = 1; //a必须出现 optional string b = 2; //b是可选的 repeated int32 c = 3; //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] uint64 Uses variable-length encoding.

sint32

int

int32

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

sint64

long

int64

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

fixed32

int[1]

uint32

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

fixed64

long[1]

uint64

总是8个字节。如果数值总是比总是比256大的话,这个类型会比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文件内容如下所示:

 1 message Student 2 { 3     required string id = 1; 4     required string name = 2; 5     required string gender = 3; 6     required int32  age = 4; 7     required string object = 5; 8     required string home_address = 6; 9     required string phone = 7; 10 }

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

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

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

 2 

 3 #ifndef PROTOBUF_C_student_2eproto__INCLUDED  4 #define PROTOBUF_C_student_2eproto__INCLUDED

 5 

 6 #include <google/protobuf-c/protobuf-c.h>

 7 

 8 PROTOBUF_C_BEGIN_DECLS  9 

10 

11 typedef struct _Student Student; 12 

13 

14 /* --- enums --- */

15 

16 

17 /* --- messages --- */

18 

19 struct _Student 20 { 21   ProtobufCMessage base; 22   char *id; 23   char *name; 24   char *gender; 25  int32_t age; 26   char *object; 27   char *home_address; 28   char *phone; 29 }; 30 #define STUDENT__INIT \

31  { PROTOBUF_C_MESSAGE_INIT (&student__descriptor) \ 32     , NULL, NULL, NULL, 0, NULL, NULL, NULL } 33 

34 

35 /* Student methods */

36 void student__init 37                      (Student         *message); 38 size_t student__get_packed_size 39                      (const Student   *message); 40 size_t student__pack 41                      (const Student   *message, 42                       uint8_t             *out); 43 size_t student__pack_to_buffer 44                      (const Student   *message, 45                       ProtobufCBuffer     *buffer); 46 Student *

47  student__unpack 48                      (ProtobufCAllocator  *allocator, 49  size_t len, 50                       const uint8_t       *data); 51 void student__free_unpacked 52                      (Student *message, 53                       ProtobufCAllocator *allocator); 54 /* --- per-message closures --- */

55 

56 typedef void (*Student_Closure) 57                  (const Student *message, 58                   void *closure_data); 59 

60 /* --- services --- */

61 

62 

63 /* --- descriptors --- */

64 

65 extern const ProtobufCMessageDescriptor student__descriptor; 66 

67 PROTOBUF_C_END_DECLS 68 

69 

70 #endif  /* PROTOBUF_student_2eproto__INCLUDED */

测试proto程序如下所示:

 1 #include <stdio.h>

 2 #include <errno.h>

 3 #include <stdlib.h>

 4 #include <string.h>

 5 #include "student.pb-c.h"

 6 

 7 #define ID_LEN         11

 8 #define NAME_LEN       32

 9 #define GENDER_LEN     10

 10 #define OBJECT_LEN     20

 11 #define HOME_ADDR_LEN  96

 12 #define PHONE_LEN      12

 13 

 14 static int malloc_student_info(Student *stu)  15 {  16     stu->id = (char*)malloc(ID_LEN);  17     if (!stu->id)  18  {  19     goto FAILED;  20  }  21     stu->name = (char*)malloc(NAME_LEN);  22     if (!stu->name)  23  {  24     goto FAILED;  25  }  26     stu->gender = (char*)malloc(GENDER_LEN);  27     if (!stu->gender)  28  {  29     goto FAILED;  30  }  31     stu->object = (char*)malloc(OBJECT_LEN);  32     if (!stu->object)  33  {  34     goto FAILED;  35  }  36     stu->home_address = (char*)malloc(HOME_ADDR_LEN);  37     if (!stu->home_address)  38  {  39     goto FAILED;  40  }  41     stu->phone = (char*)malloc(PHONE_LEN);  42     if (!stu->phone)  43  {  44     goto FAILED;  45  }  46     return 0;  47 FAILED:  48     fprintf(stdout, "malloc error.errno:%u,reason:%s\n",  49  errno, strerror(errno));  50     return -1;  51 }  52 

 53 static void free_student_info(Student *stu)  54 {  55     if (stu->id)  56  {  57     free(stu->id);  58     stu->id = NULL;  59  }  60     if (stu->name)  61  {  62     free(stu->name);  63     stu->name = NULL;  64  }  65     if (stu->gender)  66  {  67     free(stu->gender);  68     stu->gender = NULL;  69  }  70     if (stu->object)  71  {  72     free(stu->object);  73     stu->object = NULL;  74  }  75     if (stu->home_address)  76  {  77     free(stu->home_address);  78     stu->home_address = NULL;  79  }  80     if (stu->phone)  81  {  82     free(stu->phone);  83     stu->phone = NULL;  84  }  85 }  86 

 87 static void set_student_info(Student *stu)  88 {  89     const char *id = "2013111011";  90     const char *name = "Anker";  91     const char *gender = "male";  92     const char *object = "computer";  93     const char *address = "shen zheng";  94     const char *phone = "0102345678";  95     

 96     strncpy(stu->id, id, ID_LEN);  97     strncpy(stu->name, name, NAME_LEN);  98     strncpy(stu->gender, gender, GENDER_LEN);  99     stu->age = 23; 100     strncpy(stu->object, object, OBJECT_LEN); 101     strncpy(stu->home_address, address, HOME_ADDR_LEN); 102     strncpy(stu->phone, phone, PHONE_LEN); 103 } 104 

105 void print_student_info(Student *stu) 106 { 107     printf("id: %s\n",stu->id); 108     printf("name: %s\n",stu->name); 109     printf("age: %d\n",stu->age); 110     printf("gender:%s\n",stu->gender); 111     printf("object: %s\n",stu->object); 112     printf("home address: %s\n",stu->home_address); 113     printf("phone: %s\n",stu->phone); 114 } 115 

116 int main() 117 { 118     Student stu = STUDENT__INIT; 119     void *buf = NULL; 120     unsigned int len ; 121     Student *msg = NULL; 122 

123     if (malloc_student_info(&stu) == -1) { 124         exit(0); 125  } 126     set_student_info(&stu); 127 

128     //get student packed size

129     len = student__get_packed_size(&stu); 130     printf("size of student info : %u\n",len); 131     buf = malloc(len); 132     //put student info pack to buf

133     student__pack(&stu, buf); 134 

135     //unpack student info from buf

136     msg = student__unpack(NULL, len, buf); 137  print_student_info(msg); 138     //free msg

139  student__free_unpacked(msg, NULL); 140 

141  free(buf); 142     free_student_info(&stu); 143 

144     return 0; 145 }

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

测试结果如下所示:

protobuf-c的学习总结

3、参考网址

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

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

你可能感兴趣的:(protobuf)