每天早晨叫醒你的不是闹钟,而是梦想

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  62 Posts :: 0 Stories :: 5 Comments :: 0 Trackbacks

常用链接

留言簿(1)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 转载自:Protocol Buffers Language Guide之proto文件类型格式分析[关键点翻译] | 漂泊如风
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、 标量值类型

标量消息字段有表中以下几种(对应项为自动生成的类中的类型):

.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

3、 Optional字段的默认值

设定方法如: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(), andAddExtension().

说明:扩展字段可以是任何字段类型,包括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文件可以同时被指定编译。

posted on 2011-04-05 18:29 沛沛 阅读(652) 评论(0)  编辑 收藏 引用 所属分类: 开源库

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理