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