Google Protocol Buffers(转载)
介绍
Google Protocol Buffers是一个语言中立,平台中立,可扩展的序列化结构数据的方式可用于通讯协议,数据存储等方面。目前支持C\C++,Java,Python等语言,使用proto文件(类似于idl)来定义消息和数据格式,proto类似于xml,但是比xml更简单且速度更快。官方文档中的和XML的对比:
1. 比XML小3-10倍
2. 比XML快20-100倍
3. 比XML更加清晰,更不容易产生歧义
4. 比XML更易于得到类用于编程
下载、编译和安装
(1)下载
下载地址:http://code.google.com/p/protobuf/downloads/list
当前最新版本为:protobuf-2.3.0,本文下载文件为protobuf-2.3.0.tar.bz2,平台为XP SP3,开发环境为C++ VS2005,Java jdk java version "1.6.0_18"。将文件加压到C盘根目录,主文件位于C:\protobuf-2.3.0\protobuf-2.3.0目录下。
(2)编译
打算使用C++和Java两种语言来测试。使用VS2005编译proto,VS工程目录位于vsprojects目录中,工程名字为“protobuf.sln”,使用VS打开进行编译,编译过程中可能会由于编译的顺序报错误,可以使用手工逐个顺序编译生成,一般会比较顺利。编译完成会在目录vsprojects下的Debug目录中生成lib和exe文件。
生成清单如下:
exe文件:
2010-04-15 09:51 950,272 lite-test.exe
2010-04-15 09:50 3,219,456 protoc.exe
2010-04-15 09:48 9,228,288 tests.exe
2010-04-15 09:56 2,519,040 test_plugin.exe
4 个文件 15,917,056 字节
lib文件:
2010-04-15 09:50 2,685,922 libprotobuf-lite.lib
2010-04-15 09:56 24,100,794 libprotobuf.lib
2010-04-15 09:56 17,302,068 libprotoc.lib
3 个文件 44,088,784 字节
0 个目录 1,545,060,352 可用字节
(3)测试和安装
在cmd shell中:
Ø C:\protobuf-2.3.0\protobuf-2.3.0\vsprojects\Debug>tests.exe
[ FAILED ] 1 test, listed below:
[ FAILED ] CommandLineInterfaceTest.GeneratorPluginNotFound
1 FAILED TEST
问题待查,根据失败信息,应该不影响测试
Ø C:\protobuf-2.3.0\protobuf-2.3.0\vsprojects\Debug>lite-test.exe
直接PASS
使用C:\protobuf-2.3.0\protobuf-2.3.0\vsprojects\extract_includes.bat生成include文件夹,用于以后创建工程使用。在C:\protobuf-2.3.0\目录下建立bin和lib目录,将protoc.exe拷贝到bin目录中,将libprotobuf.lib,libprotobuf-lite.lib和libprotoc.lib三个库拷贝到lib目录中,将include拷贝到C:\protobuf-2.3.0目录下。
(4) 代码测试
通过proto文件protobuf会帮我们生成数据中字段的操作方法,提供数据序列化等功能,极大地节省了我们对于数据消息结构进行自己编解码的工作,具体代码可以见example中的例子。
people.proto
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
代码使用
Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
从文件读取:
fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
在C:\protobuf-2.3.0\protobuf-2.3.0\examples目录下,有一个简单的测试例子。同时包含测试代码C++, Java,Python的添加和显示代码。在Linux下可以直接使用make来进行编译测试。如果单独生成"make cpp","make java"或者 "make python"。但是测试例子没有提供VS工程,需要自己建立。
addressbook.proto:
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}
C++:
CMD窗口下:
C:\protobuf-2.3.0\protobuf-2.3.0\examples>protoc -I=./ --cpp_out=./ addressbook.proto
将proto文件生成的文件放到当前目录。
生成文件:addressbook.pb.h, addressbook.pb.cc
建立一个空的win32 控制台程序,将add_person.cc,addressbook.pb.h, addressbook.pb.cc添加进工程。
在工程属性中添加:
include目录
"C:\protobuf-2.3.0\include"
库包含路径:
C:\protobuf-2.3.0\lib\libprotobuf.lib
C:\protobuf-2.3.0\lib\libprotobuf-lite.lib
C:\protobuf-2.3.0\lib\libprotoc.lib
同样的方法编译add_person.cc
测试结果如下:
Java:
Java的代码位于C:\protobuf-2.3.0\protobuf-2.3.0\java目录中。Google推荐的生成jar的方式是使用Apache的一个开源工具Maven,但是经过个人测试在XP中未正常编译成功,详细步骤可以查看当前目录下的README.txt,可能Maven的安装过程中出现问题。于是采用了不使用Maven编译:
Installation - Without Maven
1)使用C++代码生成protoc.exe,前面步骤已经实现
2)在java目录下执行:
protoc --java_out=src/main/java -I../src ../src/google/protobuf/descriptor.proto
用于生成com\google\protobuf\DescriptorProtos.java,如果缺少此步骤,在以后的编译中会报错找不到类DescriptorProtos.java。
然后我们就可以使用任何熟悉的方法来编译Java代码了,安装已经生成的类,可以考虑jar打包后进行发布
生成proto对应的Java代码,此处生成到了java源代码目录下
C:\protobuf-2.3.0\protobuf-2.3.0\examples>protoc -I=./ --java_out=C:\protobuf-2. \
3.0\protobuf-2.3.0\java\src\main\java ./addressbook.proto
编译ListPeople.java
C:\protobuf-2.3.0\protobuf-2.3.0\examples>javac -classpath C:\protobuf-2.3.0\pro
tobuf-2.3.0\java\src\main\java ListPeople.java
运行ListPeople.java
C:\protobuf-2.3.0\protobuf-2.3.0\examples>java -classpath C:\protobuf-2.3.0\prot
obuf-2.3.0\java\src\main\java ListPeople addr.dat
Person ID: 1
Name: diwh
E-mail address: dwh0403@163.com
Mobile phone #: 12345678
用于只是简单测试,所以没将java代码jar打包,而且没有将包路径设置到CLASSPATH环境变量中,仅仅使用了命令行的-classpath参数传递。
(5) 扩展信息
http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/proto.html
总结
经过测试可知Google Protocol Buffers很好得支持了多语言跨平台开发中进行通信的目的,而且数据结构还很好地支持序列化,方便与文件保存。