Protocol Buffer 新手指南

Protocol Buffers简介

Protocol Buffers
google/protobuf
Google Protocol Buffer 的使用和原理
数据传输格式有很多种,最常见XML和JSON,这两种格式生成速度非常快,但是解析的效率却很低。尤其在数据量非常大的情况下,会卡住好半天。并且这种格式的传输也会使得传输所耗费流量变大。解析效率最高,传输消耗流量最小的数据格式自然是Buffer。很多公司都封装过自己的Buffer流传输的模块。Google公司将他们封装的Buffer流模块给贡献了出来!也就是我这里所提到的Protocol Buffers。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

Protocol Buffers编译安装

参考
C++ Installation - Unix
安装步骤总结如下:

1
2
3
4
5
6
7
$ sudo apt-get install autoconf automake libtool curl
$ ./autogen.sh
$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig

下载源码

从Github下载最新的代码仓库,对应的版本是@5e933847cc9e7826f1a9ee8b3dc1df4960b1ea5d

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
huzhifeng@ubuntu1404srv:~$ mkdir -p ProtocolBuffer
huzhifeng@ubuntu1404srv:~$ cd ProtocolBuffer/
huzhifeng@ubuntu1404srv:~/ProtocolBuffer$ git clone https://github.com/google/protobuf.git
Cloning into 'protobuf'...
remote: Counting objects: 31164, done.
remote: Total 31164 (delta 0), reused 0 (delta 0), pack-reused 31163
Receiving objects: 100% (31164/31164), 30.04 MiB | 37.00 KiB/s, done.
Resolving deltas: 100% (20856/20856), done.
Checking connectivity... done.
huzhifeng@ubuntu1404srv:~/ProtocolBuffer$
huzhifeng@ubuntu1404srv:~/ProtocolBuffer$ cd protobuf
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ git log -1
commit 5e933847cc9e7826f1a9ee8b3dc1df4960b1ea5d
Merge: ca3dc15 79a23c4
Author: Thomas Van Lenten <thomasvl@google.com>
Date: Thu Mar 17 17:06:33 2016 -0400
Merge pull request #1325 from thomasvl/shrink_overhead
Shrink ObjC overhead (generated size and some runtime sizes)
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$

安装依赖

安装如下依赖

1
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ sudo apt-get install -y autoconf automake libtool curl

执行./autogen.sh

./autogen.sh用于生成configure脚本

1
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ ./autogen.sh

由于gmock的下载地址gmock-1.7.0.zip被墙了,需要用代理下载,修改下载命令curl,传递ShadowSocks代理URL地址即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ ./autogen.sh
Google Mock not present. Fetching gmock-1.7.0 from the web...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:02:08 --:--:-- 0curl: (7) Failed to connect to googlemock.googlecode.com port 443: Connection timed out
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ grep -wn curl autogen.sh
12: # make curl silent
34: curl $curlopts -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ cp autogen.sh autogen.sh.bak
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ sed -i "s/curl \$curlopts/curl \$curlopts --proxy http:\/\/192.168.10.10:1080/g" autogen.sh
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ diff autogen.sh autogen.sh.bak
34c34
< curl $curlopts --proxy http://192.168.10.10:1080 -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip
---
> curl $curlopts -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$

重新执行./autogen.sh

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
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ ./autogen.sh
Google Mock not present. Fetching gmock-1.7.0 from the web...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2116k 100 2116k 0 0 287k 0 0:00:07 0:00:07 --:--:-- 277k
+ autoreconf -f -i -Wall,no-obsolete
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `build-aux'.
libtoolize: copying file `build-aux/ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'.
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
configure.ac:27: installing 'build-aux/compile'
parallel-tests: installing 'build-aux/test-driver'
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `build-aux'.
libtoolize: copying file `build-aux/ltmain.sh'
libtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.ac and
libtoolize: rerunning libtoolize, to keep the correct libtool macros in-tree.
libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am.
configure.ac:22: installing 'build-aux/compile'
parallel-tests: installing 'build-aux/test-driver'
libtoolize: putting auxiliary files in `.'.
libtoolize: copying file `./ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'.
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
configure.ac:60: installing './ar-lib'
configure.ac:56: installing './compile'
configure.ac:41: installing './config.guess'
configure.ac:41: installing './config.sub'
configure.ac:43: installing './install-sh'
configure.ac:43: installing './missing'
conformance/Makefile.am: installing './depcomp'
parallel-tests: installing './test-driver'
+ rm -rf autom4te.cache config.h.in~
+ exit 0
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$

编译安装

依次执行如下命令

1
2
3
4
5
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ ./configure
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ make
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ make check
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ sudo make install
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ sudo ldconfig

默认安装到了/usr/local/,如果想安装到其它路径,需要在configure时手动指定

1
2
3
4
5
6
7
8
9
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ which protoc
/usr/local/bin/protoc
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ ls /usr/local/lib/libproto*
/usr/local/lib/libprotobuf.a /usr/local/lib/libprotobuf-lite.so.10 /usr/local/lib/libprotoc.a
/usr/local/lib/libprotobuf.la /usr/local/lib/libprotobuf-lite.so.10.0.0 /usr/local/lib/libprotoc.la
/usr/local/lib/libprotobuf-lite.a /usr/local/lib/libprotobuf.so /usr/local/lib/libprotoc.so
/usr/local/lib/libprotobuf-lite.la /usr/local/lib/libprotobuf.so.10 /usr/local/lib/libprotoc.so.10
/usr/local/lib/libprotobuf-lite.so /usr/local/lib/libprotobuf.so.10.0.0 /usr/local/lib/libprotoc.so.10.0.0
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$

官网C++例子

Protocol Buffer Basics: C++

协议格式文件

Defining Your Protocol Format

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
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ cd ..
huzhifeng@ubuntu1404srv:~/ProtocolBuffer$ mkdir -p examples
huzhifeng@ubuntu1404srv:~/ProtocolBuffer$ cd examples/
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ touch addressbook.proto
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ cat -n addressbook.proto
1 package tutorial;
2
3 message Person {
4 required string name = 1;
5 required int32 id = 2;
6 optional string email = 3;
7
8 enum PhoneType {
9 MOBILE = 0;
10 HOME = 1;
11 WORK = 2;
12 }
13
14 message PhoneNumber {
15 required string number = 1;
16 optional PhoneType type = 2 [default = HOME];
17 }
18
19 repeated PhoneNumber phone = 4;
20 }
21
22 message AddressBook {
23 repeated Person person = 1;
24 }
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$

编译生成API头文件和源代码

Compiling Your Protocol Buffers
说明如下:

  1. 需要指定SRC_DIR和DST_DIR,默认使用当前目录即可
  2. 如果编译其它语言例如Python/Java/JS/Ruby,分别使用使用--python_out/--java_out/--js_out/--ruby_out
  3. 最终会生成一个头文件和一个源文件
    1
    2
    3
    4
    5
    6
    7
    8
    huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ protoc addressbook.proto
    Missing output directives.
    huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ export SRC_DIR=.
    huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ export DST_DIR=.
    huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
    [libprotobuf WARNING google/protobuf/compiler/parser.cc:547] No syntax specified for the proto file: addressbook.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)
    huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ ls
    addressbook.pb.cc addressbook.pb.h addressbook.proto

写消息

Writing A Message
代码如下:

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
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ touch writer.cc
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ cat -n writer.cc
1 #include <iostream>
2 #include <fstream>
3 #include <string>
4 #include "addressbook.pb.h"
5 using namespace std;
6
7 // This function fills in a Person message based on user input.
8 void PromptForAddress(tutorial::Person* person) {
9 cout << "Enter person ID number: ";
10 int id;
11 cin >> id;
12 person->set_id(id);
13 cin.ignore(256, '\n');
14
15 cout << "Enter name: ";
16 getline(cin, *person->mutable_name());
17
18 cout << "Enter email address (blank for none): ";
19 string email;
20 getline(cin, email);
21 if (!email.empty()) {
22 person->set_email(email);
23 }
24
25 while (true) {
26 cout << "Enter a phone number (or leave blank to finish): ";
27 string number;
28 getline(cin, number);
29 if (number.empty()) {
30 break;
31 }
32
33 tutorial::Person::PhoneNumber* phone_number = person->add_phone();
34 phone_number->set_number(number);
35
36 cout << "Is this a mobile, home, or work phone? ";
37 string type;
38 getline(cin, type);
39 if (type == "mobile") {
40 phone_number->set_type(tutorial::Person::MOBILE);
41 } else if (type == "home") {
42 phone_number->set_type(tutorial::Person::HOME);
43 } else if (type == "work") {
44 phone_number->set_type(tutorial::Person::WORK);
45 } else {
46 cout << "Unknown phone type. Using default." << endl;
47 }
48 }
49 }
50
51 // Main function: Reads the entire address book from a file,
52 // adds one person based on user input, then writes it back out to the same
53 // file.
54 int main(int argc, char* argv[]) {
55 // Verify that the version of the library that we linked against is
56 // compatible with the version of the headers we compiled against.
57 GOOGLE_PROTOBUF_VERIFY_VERSION;
58
59 if (argc != 2) {
60 cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
61 return -1;
62 }
63
64 tutorial::AddressBook address_book;
65
66 {
67 // Read the existing address book.
68 fstream input(argv[1], ios::in | ios::binary);
69 if (!input) {
70 cout << argv[1] << ": File not found. Creating a new file." << endl;
71 } else if (!address_book.ParseFromIstream(&input)) {
72 cerr << "Failed to parse address book." << endl;
73 return -1;
74 }
75 }
76
77 // Add an address.
78 PromptForAddress(address_book.add_person());
79
80 {
81 // Write the new address book back to disk.
82 fstream output(argv[1], ios::out | ios::trunc | ios::binary);
83 if (!address_book.SerializeToOstream(&output)) {
84 cerr << "Failed to write address book." << endl;
85 return -1;
86 }
87 }
88
89 // Optional: Delete all global objects allocated by libprotobuf.
90 google::protobuf::ShutdownProtobufLibrary();
91
92 return 0;
93 }
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$

编译命令如下:
直接编译是不行的

1
2
3
4
5
6
7
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ g++ writer.cc addressbook.pb.cc
/tmp/ccTzwbXU.o: In function `main':
writer.cc:(.text+0x2a8): undefined reference to `google::protobuf::internal::VerifyVersion(int, int, char const*)'
writer.cc:(.text+0x3a2): undefined reference to `google::protobuf::Message::ParseFromIstream(std::istream*)'
writer.cc:(.text+0x463): undefined reference to `google::protobuf::Message::SerializeToOstream(std::ostream*) const'
writer.cc:(.text+0x4b4): undefined reference to `google::protobuf::ShutdownProtobufLibrary()'
/tmp/ccTzwbXU.o: In function `google::protobuf::internal::GetEmptyStringAlreadyInited()':

指定头文件路径和库文件路径也不行,头文件位于/usr/local/include/,库文件位于/usr/local/lib/

1
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ g++ -I /usr/local/include/ -L /usr/local/lib/ -lprotobuf writer.cc addressbook.pb.cc

根据错误提示Google搜索到了问题原因,就是要把-lprotobuf放到最后
Can’t compile example from google protocol buffers
使用如下命令均可编译成功

1
2
3
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ g++ -I /usr/local/include/ -L /usr/local/lib/ writer.cc addressbook.pb.cc -lprotobuf
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ g++ writer.cc addressbook.pb.cc -lprotobuf
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ g++ -o writer writer.cc addressbook.pb.cc -lprotobuf

读消息

Reading A Message
代码如下:

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
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ touch reader.cc
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ cat -n reader.cc
1 #include <iostream>
2 #include <fstream>
3 #include <string>
4 #include "addressbook.pb.h"
5 using namespace std;
6
7 // Iterates though all people in the AddressBook and prints info about them.
8 void ListPeople(const tutorial::AddressBook& address_book) {
9 for (int i = 0; i < address_book.person_size(); i++) {
10 const tutorial::Person& person = address_book.person(i);
11
12 cout << "Person ID: " << person.id() << endl;
13 cout << " Name: " << person.name() << endl;
14 if (person.has_email()) {
15 cout << " E-mail address: " << person.email() << endl;
16 }
17
18 for (int j = 0; j < person.phone_size(); j++) {
19 const tutorial::Person::PhoneNumber& phone_number = person.phone(j);
20
21 switch (phone_number.type()) {
22 case tutorial::Person::MOBILE:
23 cout << " Mobile phone #: ";
24 break;
25 case tutorial::Person::HOME:
26 cout << " Home phone #: ";
27 break;
28 case tutorial::Person::WORK:
29 cout << " Work phone #: ";
30 break;
31 }
32 cout << phone_number.number() << endl;
33 }
34 }
35 }
36
37 // Main function: Reads the entire address book from a file and prints all
38 // the information inside.
39 int main(int argc, char* argv[]) {
40 // Verify that the version of the library that we linked against is
41 // compatible with the version of the headers we compiled against.
42 GOOGLE_PROTOBUF_VERIFY_VERSION;
43
44 if (argc != 2) {
45 cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
46 return -1;
47 }
48
49 tutorial::AddressBook address_book;
50
51 {
52 // Read the existing address book.
53 fstream input(argv[1], ios::in | ios::binary);
54 if (!address_book.ParseFromIstream(&input)) {
55 cerr << "Failed to parse address book." << endl;
56 return -1;
57 }
58 }
59
60 ListPeople(address_book);
61
62 // Optional: Delete all global objects allocated by libprotobuf.
63 google::protobuf::ShutdownProtobufLibrary();
64
65 return 0;
66 }
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$

编译命令如下:

1
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ g++ -o reader reader.cc addressbook.pb.cc -lprotobuf

测试

先执行两次写程序添加两个联系人

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
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ ./writer
Usage: ./writer ADDRESS_BOOK_FILE
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ ./writer MyAddressBook.bin
MyAddressBook.bin: File not found. Creating a new file.
Enter person ID number: 1001
Enter name: huzhifeng
Enter email address (blank for none): zhifeng.hu@hotmail.com
Enter a phone number (or leave blank to finish): 13701234567
Is this a mobile, home, or work phone? mobile
Enter a phone number (or leave blank to finish): 07311234567
Is this a mobile, home, or work phone? home
Enter a phone number (or leave blank to finish): 07551234567
Is this a mobile, home, or work phone? work
Enter a phone number (or leave blank to finish):
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ ./writer MyAddressBook.bin
Enter person ID number: 1002
Enter name: zhangsan
Enter email address (blank for none): zhangsan@gmail.com
Enter a phone number (or leave blank to finish): 13800138000
Is this a mobile, home, or work phone? mobile
Enter a phone number (or leave blank to finish): 10086
Is this a mobile, home, or work phone? home
Enter a phone number (or leave blank to finish): 1234567890
Is this a mobile, home, or work phone? work
Enter a phone number (or leave blank to finish):

然后执行读程序遍历联系人

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ ./reader
Usage: ./reader ADDRESS_BOOK_FILE
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ ./reader MyAddressBook.bin
Person ID: 1001
Name: huzhifeng
E-mail address: zhifeng.hu@hotmail.com
Mobile phone #: 13701234567
Home phone #: 07311234567
Work phone #: 07551234567
Person ID: 1002
Name: zhangsan
E-mail address: zhangsan@gmail.com
Mobile phone #: 13800138000
Home phone #: 10086
Work phone #: 1234567890
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$

Github代码仓库例子C++

上面的例子已经比较旧了,最后更新于2014年9月
其实从Github下载的源码中已经包含了最新的示例程序,而且默认协议格式是syntax = "proto3"
protobuf/examples/
说明如下:

  1. 如果想编译所有语言的,直接执行make
  2. 如果只想编译C++的,执行make cpp

查看README.txt和Makefile

1
2
3
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/examples$ cd ../protobuf/examples/
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ cat -n README.txt
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ cat -n Makefile

尝试编译make cpp,提示找不到pkg-config

1
2
3
4
5
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ make cpp
pkg-config --cflags protobuf # fails if protobuf is not installed
/bin/sh: 1: pkg-config: not found
make: *** [add_person_cpp] Error 127
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$

使用命令sudo apt-get install -y pkg-config进行安装

1
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ sudo apt-get install -y pkg-config

重新编译OK了

1
2
3
4
5
6
7
8
9
10
11
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ make cpp
pkg-config --cflags protobuf # fails if protobuf is not installed
-pthread -I/usr/local/include
c++ add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
pkg-config --cflags protobuf # fails if protobuf is not installed
-pthread -I/usr/local/include
c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ pkg-config --cflags --libs protobuf
-pthread -I/usr/local/include -pthread -L/usr/local/lib -lprotobuf -lpthread
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$

测试步骤参考之前的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ ./add_person_cpp MyAddressBook.bin
MyAddressBook.bin: File not found. Creating a new file.
Enter person ID number: 1001
Enter name: huzhifeng
Enter email address (blank for none): zhifeng.hu@hotmail.com
Enter a phone number (or leave blank to finish): 13701234567
Is this a mobile, home, or work phone? mobile
Enter a phone number (or leave blank to finish):
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ ./list_people_cpp MyAddressBook.bin
Person ID: 1001
Name: huzhifeng
E-mail address: zhifeng.hu@hotmail.com
Mobile phone #: 13701234567
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ hexdump -C MyAddressBook.bin
00000000 0a 35 0a 09 68 75 7a 68 69 66 65 6e 67 10 e9 07 |.5..huzhifeng...|
00000010 1a 16 7a 68 69 66 65 6e 67 2e 68 75 40 68 6f 74 |..zhifeng.hu@hot|
00000020 6d 61 69 6c 2e 63 6f 6d 22 0d 0a 0b 31 33 37 30 |mail.com"...1370|
00000030 31 32 33 34 35 36 37 |1234567|
00000037
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$

Github代码仓库例子Python

安装说明详见
protobuf/python/

1
2
3
4
5
6
7
8
9
10
11
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ python -V
Python 2.7.6
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ protoc --version
libprotoc 3.0.0
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf$ cd python/
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ python setup.py build
Traceback (most recent call last):
File "setup.py", line 11, in <module>
from setuptools import setup, Extension, find_packages
ImportError: No module named setuptools
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$

需要先安装pip和setuptools,可以参考
pip Installation
How to Install Pip on Ubuntu 14.04 LTS
Installing pip/setuptools/wheel
有两种方法安装pip,一种是通过apt-get,另一种是通过get-pip.py,这里选择apt-get的方式

1
2
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ sudo apt-get install -y python-pip
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ sudo pip install -U pip setuptools

重新执行python setup.py buildpython setup.py test

1
2
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ python setup.py build
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ python setup.py test

最后安装到/usr/local/目录下

1
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ sudo python setup.py install

测试例子

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
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/python$ cd ../examples/
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ make python
protoc --cpp_out=. --java_out=. --python_out=. addressbook.proto
Writing shortcut script add_person_python...
Writing shortcut script list_people_python...
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ ./add_person_python MyAddressBook.bin
Enter person ID number: 1002
Enter name: lisi
Enter email address (blank for none): lisi@gmail.com
Enter a phone number (or leave blank to finish): 13800138000
Is this a mobile, home, or work phone? mobile
Enter a phone number (or leave blank to finish): 10086
Is this a mobile, home, or work phone? work
Enter a phone number (or leave blank to finish): 01234567890
Is this a mobile, home, or work phone? home
Enter a phone number (or leave blank to finish):
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$ ./list_people_python MyAddressBook.bin
Person ID: 1001
Name: huzhifeng
E-mail address: zhifeng.hu@hotmail.com
Mobile phone #: 13701234567
Person ID: 1002
Name: lisi
E-mail address: lisi@gmail.com
Mobile phone #: 13800138000
Work phone #: 10086
Home phone #: 01234567890
huzhifeng@ubuntu1404srv:~/ProtocolBuffer/protobuf/examples$

其它语言支持

protobuf-c

protobuf-c
参考
linux环境下protobuf-c的编译使用

nanopb

nanopb
nanopb@Github

protobuf@OpenWrt

packages/libs/protobuf/

protobuf@Lua

sean-lin/protoc-gen-lua
djungelorm/protobuf-lua
protoc-gen-lua 编译、安装、使用教程
Xcode配置ProtoBuf教程

EOF