首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

Google Protocol Buffers浅析(1)转载

2013-12-19 
Google Protocol Buffers浅析(一)转载message?Person?{??required?string?name??1??required?int32?id?

Google Protocol Buffers浅析(一)转载
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;
??
??required?bytes??unsure = 5;??????//Add?byte?array?here????
}

message?AddressBook?{
??repeated?Person?person?=?1;
}

???? 诚如你看到的一样,消息格式定义很简单,对于每个字段而言都有一个修饰符(required/repeated/optional)、字段类型(bool/string/bytes/int32等)和字段标签(Tag)组成。

???? 三个修饰符从词义上可以很清楚的弄明白,

??? 1)对于required的字段而言,初值是必须要提供的,否则字段的便是未初始化的。在Debug模式的buffer库下编译的话,序列化话的时候可能 会失败,而且在反序列化的时候对于该字段的解析会总是失败的。所以,对于修饰符为required的字段,请在序列化的时候务必给予初始化。

????2)对于optional的字段而言,如果未进行初始化,那么一个默认值将赋予该字段,当然也可以指定默认值,如上述proto定义中的PhoneType字段类型。

??? 3)对于repeated的字段而言,该字段可以重复多个,google提供的这个addressbook例子便有个很好的该修饰符的应用场景,即每个人 可能有多个电话号码。在高级语言里面,我们可以通过数组来实现,而在proto定义文件中可以使用repeated来修饰,从而达到相同目的。当然,出现 0次也是包含在内的。??????

??? 其中字段标签标示了字段在二进制流中存放的位置,这个是必须的,而且序列化与反序列化的时候相同的字段的Tag值必须对应,否则反序列化会出现意想不到的问题。

?? ?

?? ? 三、编译proto文件,生成特定语言数据的数据定义代码 ?

?? ? 在定义好了proto文件,就可以将该文件作为protocol buffers编译器的输入文件,编译产生特定语言的数据定义代码文件了。本文主要是针对C++语言,所以使用编译器后生成的是.h与.cc的代码文件。 对于C++、Java还有Python都有各自的编译器,下载地址:http://code.google.com/p/protobuf/downloads/list??

?? ? 当你下载完了对应的编译器二进制文件后,就可以使用下列命令来完成编译过程:

?? ????//?required?string?number?=?1;
??inline?bool?has_number()?const;
??inline?void?clear_number();
??inline?const?::std::string&?number()?const;
??inline?void?set_number(const?::std::string&?value);
??inline?void?set_number(const?char*?value);
??inline?::std::string*?mutable_number();

??????可以看出,对于每个字段会生成一个has函数(has_number)、clear清除函数(clear_number)、set函数 (set_number)、get函数(number和mutable_number)。这儿解释下get函数中的两个函数的区别,对于原型为const std::string &number() const的get函数而言,返回的是常量字段,不能对其值进行修改。但是在有一些情况下,对字段进行修改是必要的,所以提供了一个mutable版的 get函数,通过获取字段变量的指针,从而达到改变其值的目的。

????? 而对于字段修饰符为repeated的字段生成的函数,则稍微有一些不同,如phone字段,则编译器会为其产生如下的代码:?

??//?repeated?.Person.PhoneNumber?phone?=?4;
??inline?int?phone_size()?const;
??inline?void?clear_phone();
??inline?const?::google::protobuf::RepeatedPtrField<?::Person_PhoneNumber?>&?phone()?const;
??inline?::google::protobuf::RepeatedPtrField<?::Person_PhoneNumber?>*?mutable_phone();
??inline?const?::Person_PhoneNumber&?phone(int?index)?const;
??inline?::Person_PhoneNumber*?mutable_phone(int?index);
??inline?::Person_PhoneNumber*?add_phone();

??????可以看出,set函数变成了add函数,这个其实很好理解。上面也说过,repeated修饰的字段在高级语言中的实现可能是个数组或动态数组,所以当然通过添加的方式来加入新的字段值。而起get函数也变化很大,这个也不用多说了。

???? 好了,本文主要是对了解protocol buffer作了些简单的介绍,当然更详细的还是看官方文档。下篇文章开始将介绍怎么利用protocol buffers来完成序列化与反序列化数据。

???? 欢迎转载,转载时请务必保留原文出处:http://www.cnblogs.com/royenhome?,谢谢合作!

热点排行