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

测试结果如下所示:

3、参考网址

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

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

posted @ 2013-11-10 12:41  Rabbit_Dale  阅读(46895)  评论(4编辑  收藏  举报