Protocol Buffers Language Guide之proto文件类型格式分析
2015-01-27 23:38
288 查看
1、 定义一个消息类型:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}
A.特定域的类型:两个整型变量page_number和result_per_page、一个string类型的变量query。也可以定义为其他类型如:枚举和其它message类型。
B. 指派一个标签:这个标签是唯一的,它的范围可以使1~229-1,当然19000~19999是不可以使用的,因为protocol
buffer内部使用。其中1~15保留为经常使用的消息元素。
C. 指定字段规则:指定的消息字段的规则有以下几种:a.required 一个结构良好的message必须有一个这样的字段。b.optional 结构良好的message有零个或者一个这样的字段。c.repeated 这个字段可以重复任意多次(包括零次)。说明:在repeated后面加上[packed
= true]可以取得更高效的编码。如:repeated int32 samples = 4 [package=true];
D.可以在一个文件中添加多个message,在编译生成cpp代码后,将对应多个类。
E. Proto注释的添加和cpp一样,用双斜杠即可。
F. 运行protocol
buffer 编译器按照指定的选项生成特定语言的代码,在生成的代码中包含了对proto文件中声明的变量的设定、取得、序列化消息到输出流和从输入流中分解出你的消息的操作。详细可以参考对应语言的protocol
buffer API。
2、 标量值类型
标量消息字段有表中以下几种(对应项为自动生成的类中的类型):
3、 Optional字段的默认值
设定方法如:optional int32 result_per_page = 3 [default = 10];
如果没有指定则:string默认值为空串,bool为false,数字类型的为零,枚举类型的默认值为枚举定义列表中的第一个值。
4、 枚举
外部message可以通过MessageType
5、 使用其他的message类型
message也可以作为一个类型进行使用,例如:
message SearchResponse {
repeated Result result = 1;
}
message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
当然一个message可以在不同的文件中进行定义,使用的时候可以使用import进行加入:import
“myproject/other_protos.proto”;
6、 嵌套类型
message SearchResponse {
message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
repeated Result result = 1;
}
上面例子中,result在SearchResponse中进行定义,如果希望在外部的message中调用result,你可以使用:Parent.Type:
message SomeOtherMessage {
optional SearchResponse.Result result = 1;
}
当然了也可以嵌套一个消息任意深度:
分组:在创建一个新的message类型时,这种特点一般不被赞成使用,往往用嵌套的message类型代替。
message SearchResponse {
repeated group Result = 1 {
required string url = 2;
optional string title = 3;
repeated string snippets = 4;
}
}
只是用了大括号进行括起来,注意标点!这个和上面的那个例子是一致的。
7、 更新一个消息类型
一个已经存在的message类型不再满足你的需要,在不改变以前定义的格式的基础上进行更新。遵照如下规则:
A、 不要改变已经存在字段的数字标签。
B、 任何你添加的新字段应该是optional或者repeated类型。
C、 非必须字段可以被删除,同时标签数字在你更新的message类型中不再被使用。(更好的方法是为字段更名,可以加上OBSOLETE_前缀,这样将来使用你的proto文件的用户就不能意外的使用这个数字了)
D、一个非必须的字段可以转变为一个扩展,反过来也一样,同时类型和数字保持不变。
E、 int32、uint32、int64、uint64和bool都是兼容的。
F、 sint32和sint64是兼容的,但是并不与其他整型数兼容。
G、string和bytes相互兼容。
H、 嵌入message和bytes兼容
I、 fixed32和sfixed32,fixed64和sfixed64兼容
8、 扩展
举例:
字段数字[100, 199]保留用以扩展,其他用户可以再Foo中使用这些标记数字添加新的字段,如下:
extend Foo {
optional int32 bar = 126;
}
这样就在Foo中添加了类型为int32的新字段bar,在编译生成的文件中访问扩展字段的方法稍有不同:
Foo foo;
foo.SetExtension(bar, 15);
其他的处理方法有:
and
说明:扩展字段可以是任何字段类型,包括message类型。
扩展的嵌套:
message Baz {
extend Foo {
optional int32 bar = 126;
}
...
}
C++访问扩展的方法:
Foo foo;
foo.SetExtension(Baz::bar, 15);
唯一不同的就是在bar前面加了个Baz,就这么简单。
提倡不是用嵌套的扩展。
扩展标签数字的选择:
message Foo {
extensions 1000 to max;
}
9、 包
举例:
package foo.bar;
message Open { ... }
在另外一个message中使用这个包的方法:
message Foo {
...
required foo.bar.Open open = 1;
...
}
生成的C++代码中package被声明为命名空间。Open将在命名空间foo::bar中。
10、 服务的定义
举例如下:
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
11、 选项
。。。
12、 产生你的类
下载源码,配置并编译源码生成编译器。编译参数:
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
说明:
a. LMPORT_PATH是指定你的.proto文件坐在的目录。
b. 提供以下输出:
--cpp_out在DST_DIR产生C++代码
--java_out在DST_DIR产生Java代码
--python_out在DST_DIR产生python代码
c. 必须提供一个或者多个.proto文件作为输入。当然多个.proto文件可以同时被指定编译。
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}
A.特定域的类型:两个整型变量page_number和result_per_page、一个string类型的变量query。也可以定义为其他类型如:枚举和其它message类型。
B. 指派一个标签:这个标签是唯一的,它的范围可以使1~229-1,当然19000~19999是不可以使用的,因为protocol
buffer内部使用。其中1~15保留为经常使用的消息元素。
C. 指定字段规则:指定的消息字段的规则有以下几种:a.required 一个结构良好的message必须有一个这样的字段。b.optional 结构良好的message有零个或者一个这样的字段。c.repeated 这个字段可以重复任意多次(包括零次)。说明:在repeated后面加上[packed
= true]可以取得更高效的编码。如:repeated int32 samples = 4 [package=true];
D.可以在一个文件中添加多个message,在编译生成cpp代码后,将对应多个类。
E. Proto注释的添加和cpp一样,用双斜杠即可。
F. 运行protocol
buffer 编译器按照指定的选项生成特定语言的代码,在生成的代码中包含了对proto文件中声明的变量的设定、取得、序列化消息到输出流和从输入流中分解出你的消息的操作。详细可以参考对应语言的protocol
buffer API。
2、 标量值类型
标量消息字段有表中以下几种(对应项为自动生成的类中的类型):
.proto Type | Notes | C++ Type | Java Type |
double | double | double | |
float | float | float | |
int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int |
int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long |
uint32 | Uses variable-length encoding. | uint32 | int[1] |
uint64 | 使用变长编码 | uint64 | long[1] |
sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int |
sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long |
fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 228. | uint32 | int[1] |
fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 256. | uint64 | long[1] |
sfixed32 | Always four bytes. | int32 | int |
sfixed64 | Always eight bytes. | int64 | long |
bool | bool | boolean | |
string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String |
bytes | May contain any arbitrary sequence of bytes. | string | ByteString |
设定方法如:optional int32 result_per_page = 3 [default = 10];
如果没有指定则:string默认值为空串,bool为false,数字类型的为零,枚举类型的默认值为枚举定义列表中的第一个值。
4、 枚举
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3 [default = 10];
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
optional Corpus corpus = 4 [default = UNIVERSAL];
}
外部message可以通过MessageType
.EnumType取得其中的值
5、 使用其他的message类型
message也可以作为一个类型进行使用,例如:
message SearchResponse {
repeated Result result = 1;
}
message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
当然一个message可以在不同的文件中进行定义,使用的时候可以使用import进行加入:import
“myproject/other_protos.proto”;
6、 嵌套类型
message SearchResponse {
message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
repeated Result result = 1;
}
上面例子中,result在SearchResponse中进行定义,如果希望在外部的message中调用result,你可以使用:Parent.Type:
message SomeOtherMessage {
optional SearchResponse.Result result = 1;
}
当然了也可以嵌套一个消息任意深度:
message Outer { // Level 0
message MiddleAA { // Level 1
message Inner { // Level 2
required int64 ival = 1;
optional bool booly = 2;
}
}
message MiddleBB = { // Level 1
message Inner = { // Level 2
required int32 ival = 1;
optional bool booly = 2;
}
}
}
分组:在创建一个新的message类型时,这种特点一般不被赞成使用,往往用嵌套的message类型代替。
message SearchResponse {
repeated group Result = 1 {
required string url = 2;
optional string title = 3;
repeated string snippets = 4;
}
}
只是用了大括号进行括起来,注意标点!这个和上面的那个例子是一致的。
7、 更新一个消息类型
一个已经存在的message类型不再满足你的需要,在不改变以前定义的格式的基础上进行更新。遵照如下规则:
A、 不要改变已经存在字段的数字标签。
B、 任何你添加的新字段应该是optional或者repeated类型。
C、 非必须字段可以被删除,同时标签数字在你更新的message类型中不再被使用。(更好的方法是为字段更名,可以加上OBSOLETE_前缀,这样将来使用你的proto文件的用户就不能意外的使用这个数字了)
D、一个非必须的字段可以转变为一个扩展,反过来也一样,同时类型和数字保持不变。
E、 int32、uint32、int64、uint64和bool都是兼容的。
F、 sint32和sint64是兼容的,但是并不与其他整型数兼容。
G、string和bytes相互兼容。
H、 嵌入message和bytes兼容
I、 fixed32和sfixed32,fixed64和sfixed64兼容
8、 扩展
举例:
message Foo {
// ...
extensions 100 to 199;
}
字段数字[100, 199]保留用以扩展,其他用户可以再Foo中使用这些标记数字添加新的字段,如下:
extend Foo {
optional int32 bar = 126;
}
这样就在Foo中添加了类型为int32的新字段bar,在编译生成的文件中访问扩展字段的方法稍有不同:
Foo foo;
foo.SetExtension(bar, 15);
其他的处理方法有:
HasExtension(),
ClearExtension(),
GetExtension(),
MutableExtension(),
and
AddExtension().
说明:扩展字段可以是任何字段类型,包括message类型。
扩展的嵌套:
message Baz {
extend Foo {
optional int32 bar = 126;
}
...
}
C++访问扩展的方法:
Foo foo;
foo.SetExtension(Baz::bar, 15);
唯一不同的就是在bar前面加了个Baz,就这么简单。
提倡不是用嵌套的扩展。
扩展标签数字的选择:
message Foo {
extensions 1000 to max;
}
max= 229 - 1, 或者 536,870,911.但是不包含19000~19999,具体原因参照上文。
9、 包
举例:
package foo.bar;
message Open { ... }
在另外一个message中使用这个包的方法:
message Foo {
...
required foo.bar.Open open = 1;
...
}
生成的C++代码中package被声明为命名空间。Open将在命名空间foo::bar中。
10、 服务的定义
举例如下:
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
11、 选项
。。。
12、 产生你的类
下载源码,配置并编译源码生成编译器。编译参数:
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto
说明:
a. LMPORT_PATH是指定你的.proto文件坐在的目录。
b. 提供以下输出:
--cpp_out在DST_DIR产生C++代码
--java_out在DST_DIR产生Java代码
--python_out在DST_DIR产生python代码
c. 必须提供一个或者多个.proto文件作为输入。当然多个.proto文件可以同时被指定编译。
相关文章推荐
- Protocol Buffers Language Guide之proto文件类型格式分析[关键点翻译]
- Google Protocol Buffers 实用技术:解析.proto文件和任意数据文件
- UNIX-LINUX平台可执行文件格式分析
- Unix ELF文件格式及病毒分析
- Icon文件格式分析
- wav文件格式分析详解
- BMP文件格式分析
- wab文件格式分析
- BMP文件格式分析
- SQLite数据库文件格式分析(B树的基本组织)
- Gif 文件格式分析 —— (转)
- BMP文件格式分析
- 分析现行的常用的文件格式类别
- Unix/ELF文件格式及病毒分析
- BMP文件格式分析
- UNIX/LINUX 平台可执行文件格式分析(转)
- wab文件格式分析
- BMP文件格式分析
- zt BMP 文件格式分析
- GIF 文件格式分析