http://www.cnblogs.com/javaee6/p/4849051.htmlhtml
其实用法很是简单(暂时没有涉及到tcp的封包等问题):java
主要的模板以下:c++
package tutorial; 这个包名会成为一个名字空间 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; } message AddressBook { repeated Person person = 1; }
以上的proto文件用protoc命令生成一个.h文件和一个.cc文件,这两个文件就是生成的类的定义。数组
注意:tcp
required 规定必须提供字段,不然message就是没有初始化的。ui
optional 能够设置,也能够不设置字段。不设置字段时会使用默认值,能够指定可选字段的默认值。spa
若是没有指定默认值,则对于数值类型,0是默认值;设计
对于字符串,空字符串是默认值;指针
对于bool类型,false是默认值;调试
对于嵌入的message类型,默认值是此message的默认实例或者元类型,其中每一个字段都没有设置。
对于没有显示设定值的可选或者必选字段,调用访问器老是返回字段的默认值。
repeated 定义字段能够重复屡次(包括0次)。各个重复的值的次序会保留,能够把重复字段看做是动态数组。
protoc -I=./ --cpp_out=./ XXXXXXXXXXXX.proto 其中-I指定的是proto文件所在的路径,--cpp_out是指定生成的c++类定义文件的路径,最后那个.proto指定的是具体的编写的proto文件的名称。
每一个mesage的生成的类定义会有以下的特性:
1 访问器方法: get方法就是字段的名称 set方法是set_后面加上字段的名称 如: set方法: inline void set_email(const std::string& value); inline void set_email(const char* value); get方法: inline const ::std::string& email() const; 2 has_方法: 用来判断是否为(可选或者必选)字段设置过值 如: inline bool has_email() const; 3 clear_方法: 清除字段值,使之成为空状态 如: inline void clear_email(); 4 字符串:多了mutable_方法,能够取得字段值的间接指针;还多了一个set_方法,是用char指针做为参数。 5 repeated字段,会有以下的方法: A _size方法:判断有多少个元素 如: inline int phone_size() const; B 没有has_方法 C 经过索引取得或者更新元素 如: inline const ::tutorial::Person_PhoneNumber& phone(int index) const; D add_方法:加入新的元素 如: inline ::tutorial::Person_PhoneNumber* add_phone();
2.2 枚举和嵌套类型
生成的代码含有枚举类型Person::PhoneType,其值能够是Person::MOBILE、Person::HOME、Person::WORK 生成的代码含有嵌套类Person::PhoneNumber,可是实际的名称是Person_PhoneNumber,若是须要前向声明,则须要使用名字Person_PhoneNumber。
2.3 标准消息方法
bool IsInitialized() const:是否全部必需的字段都已经设置 string DebugString() const:返回表示消息的人类可读的字符串,对于调试特别有用 void CopyFrom(const Person& from):复制 void Clear():清除全部字段
2.4 解析和序列化
A bool SerializeToString(string* output) const; 序列化message,存储到string中。注意其中的字节是二进制的,而不是文本。也就是说序列化以后,如写入文件等,你仍然看不懂,由于是二进制的。 B bool ParseFromString(const string& data); 从字符串中解析出message,这就是反序列化。 C bool SerializeToOstream(ostream* output) const; 将消息写入到C++ ostream中。 D bool ParseFromIstream(istream* input); 从C++ istream中解析出消息。 以上也就是说,protocol buffer总共有那么两种类型的交互方式:一种就是直接跟string进行交互;还有一种就是跟istrem或者ostream进行交互。
应用发布以后,未来极可能须要改进protocol buffer定义。为保证新的格式向后兼容,旧的格式向前兼容,对于新版本的定义: · 不得修改任何已有字段的序号 · 不得增长或者删除required字段 · 能够删除optional或者repeated字段 · 能够添加新的optional或者repeated字段,可是必须使用新的序号 只要遵循上述规则,则旧的程序能够很好地处理新的消息(简单地忽略新的字段)。 · 对于旧的程序:被删除的optional字段具备默认值;被删除的repeated字段是空的。新的程序也能够透明地处理旧的消息。 · 可是:新的optional字段不会出如今旧的消息中,因此(新的程序)要么显式地调用has_方法进行检查,要么在.proto文件中字段序号后面用[default=value]定义默认值。 · 并且:新的repeated字段不会出如今旧的消息中,(新的程序)无法判断是(新的程序)把它设置成空了,仍是(旧的程序)根本就没有设置这个字段,由于没有has_方法!