protobuf-c centos编译

介绍

学习protobuf-c的使用,并在pb和json进行互转

准备工作

安装编译工具

1
yum install gcc gcc-c++ automake autoconf libtool

源码下载

编译protobuf

1
2
3
4
./autogen.sh
./configure --prefix=/usr/bin/protobuf/
make
make install

编译protobuf-c

1
2
3
4
5
export PKG_CONFIG_PATH=/usr/bin/protobuf/lib/pkgconfig
./autogen.sh
./configure --prefix=/usr/bin/protobufc/
make
make install

测试demo

1
2
3
4
5
6
7
8
9
10
11
12
syntax = "proto2";  // proto3 必须加此注解

message Student
{
required string id = 1;
required string name = 2;
required string gender = 3;
required int32 age = 4;
required string object = 5;
required string home_address = 6;
required string phone = 7;
}
1
生成 c 代码: /usr/bin/protobufc/bin/protoc-c --c_out=. student.proto

test_student.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
 #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 0;
FAILED:
fprintf(stdout, "malloc error.errno:%u,reason:%s\n",
errno, strerror(errno));
return -1;
}

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 = "2013111011";
const char *name = "Anker";
const char *gender = "male";
const char *object = "computer";
const char *address = "shen zheng";
const char *phone = "0102345678";

strncpy(stu->id, id, ID_LEN);
strncpy(stu->name, name, NAME_LEN);
strncpy(stu->gender, gender, GENDER_LEN);
stu->age = 23;
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) == -1) {
exit(0);
}
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 0;
}

1
2
编译
gcc student.pb-c.c test_student.c -I /usr/bin/protobufc/include -L /usr/bin/protobufc/lib/ -lprotobuf-c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
执行:
export LD_LIBRARY_PATH="LD_LIBRARY_PATH:/usr/bin/protobufc/lib:/usr/local/lib"

./a.out , 输出

[root@localhost code]# ./a.out
size of student info : 61
id: 2013111011
name: Anker
age: 23
gender:male
object: computer
home address: shen zheng
phone: 0102345678

***交叉编译

1
./configure --host=arm-linux CC=XX CXX=XX --prefix=/usr/bin/protobufc/

pb2json and json2pb

使用依赖库protobuf2json-c

  • 编译 jansson

  • 编译protobuf2json-c

    1
    ./autogen.sh && ./configure && make && make install
  • 修改刚刚的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "protobuf2json.h"

.....

char *json_string;
int result = 0;
Student *stuNew = NULL;

//pb 2 json
result = protobuf2json_string(&stu.base, (JSON_INDENT(2) | JSON_PRESERVE_ORDER), &json_string, NULL, 0);

printf("%d,--- %s \n",result,json_string);

// json 2 pb
result = json2protobuf_string(json_string,(JSON_INDENT(2) | JSON_PRESERVE_ORDER),&student__descriptor,(ProtobufCMessage**)(&stuNew), error_string, sizeof(error_string));

print_student_info(stuNew);

//free
free(stuNew);
free(json_string);
1
2
编译:
gcc student.pb-c.c test_student.c -I /usr/bin/protobufc/include -L /usr/bin/protobufc/lib/ -lprotobuf-c -L /usr/local/lib -lprotobuf2json-c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
输出:
[root@localhost code]# ./a.out
size of student info : 61
id: 2013111011
name: Anker
age: 23
gender:male
object: computer
home address: shen zheng
phone: 0102345678
0,--- {
"id": "2013111011",
"name": "Anker",
"gender": "male",
"age": 23,
"object": "computer",
"home_address": "shen zheng",
"phone": "0102345678"
}
id: 2013111011
name: Anker
age: 23
gender:male
object: computer
home address: shen zheng
phone: 0102345678