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
测试结果如下所示:
时间: 2024-09-27 16:45:41