首页protobuf › protobuf 生成的C++代码详解

protobuf 生成的C++代码详解

Packages


如果 .proto 文件中包含 package 定义,此文件的整个内容将被放置到对应的C++命名空间中。例如,假定 package 声明为:

此 .proto 文件中所有声明将都属于命名空间 foo::bar。

Messages


假定简单的一个消息声明如下:

protocol buffer编译器生成 Foo 类,公开地(publicly)派生自 google::protobuf::Message。Foo类是一个实体类;禁止遗留下纯虚的方法没有被实现。除了 Message 中的虚方法之外,非纯虚的方法可以由 Foo 类重载也可以不重载,取决于优化模式。缺省,为了最高的速度, Foo 实现特定protocol buffer版本的所有方法。不管怎样,如果 .proto 文件包含下列行:

Foo 将仅重载运行必需的最小方法集合,和依赖于基于反射实现的剩余部分。这意味着减小了生成代码的大小,但也减小了性能。或者,如果 .proto 文件包含:

Foo 将包含所有方法的快速实现(fast implementations),但是是实现 google::protobuf::MessageLite 接口,仅包含 Message 中所有方法的一个子集。尤其,它不支持描述符(descriptors)或反射。不管怎样,以这种方式生成的代码只需要连接 libprotobuf-lite.so (Windows上是 libprotobuf-lite.lib) 而不是 libprotobuf.so(libprotobuf.lib)。”lite”库比 “full”库(完整的库)要小很多,更适用于资源受限的系统,比如手机。

你不应该创建 Foo 的子类。如果你子类化 Foo ,并且重载虚方法,重载可能被忽略,就像很多生成的方法为了提高性能被去虚拟化(de-virtualized)。

Message接口定义的方法,允许你检查、操作、读、或写整个消息,包括解析二进制字符串,以及序列化二进制字符串。除此之外, Foo 类定义了下列方法:

  • Foo(): 缺省的构造函数。
  • ~Foo(): 缺省的析构函数。
  • Foo(const Foo& other): 复制(Copy)构造函数。
  • Foo& operator=(const Foo& other): 赋值(Assignment)操作符。
  • const UnknownFieldSet& unknown_fields() const: 返回当解析信息时遇到的未知字段的集合。
  • UnknownFieldSet* mutable_unknown_fields(): 返回当解析信息时遇到的未知字段的集合的一个mutable指针。

Foo 类也定义了下列静态方法:

  • static const Descriptor& descriptor(): 返回类型的描述符。包括类型信息,有什么字段以及字段是什么类型。这可以结合reflection用来以编程的方式检查字段。
  • static const Foo& default_instance(): 返回 Foo 的 const 单例,相当于新构造的一个 Foo 实例(因此所有单独的字段(singular fields)是未设置的,所有的重复字段(repeated fields)是空的)。注意一个消息(a message)的缺省实例(default instance)通过调用它的 New() 方法可以被用作一个工厂(factory)。

一个消息可以声明在其他的消息中。如:message Foo {message Bar {} }

这种情况下,编译器(protoc)生成两个类:Foo 和 Foo_Bar. 此外,编译器在 Foo 中生成如下的typedef:

意思是你可以使用嵌入的类的类型犹如它是嵌入的类 Foo::Bar。然而,注意 C++ 不允许嵌入的类型被声明。如果你想要在其他文件中声明 Bar,并且使用此声明,你必须把它看着和Foo_Bar一样。

Fields


除了上节描述的方法,protocol buffer编译器为 .proto 文件中定义的消息中的每个字段生成一套存取器方法(accessor method)。

和存取器方法一样,编译器(protoc)为每个字段生成一个整数常量,包含它的字段编号。常量名是字母 k ,后面紧跟被转换为驼峰式大小写的字段名,然后紧跟 FieldNumber。 例如,假定字段 optional int32 foo_bar = 5;,编译器(protoc)将生成常量 static const int kFooBarFieldNumber = 5;。

Singular Numeric Fields

对于这些字段中任何一个定义:

编译器将生成下列存取器方法:

  • bool has_foo() const: 如果字段被设置返回 true。
  • int32 foo() const: 返回字段的当前值。如果字段没有被设置,返回缺省值。
  • void set_foo(int32 value): 设置字段的值。调用此方法后,has_foo() 将返回 true 以及 foo() 将返回 value。
  • void clear_foo(): 清除字段的值。调用此方法后,has_foo()将返回 false 以及 foo() 将返回缺省值。

对于其他的数值字段类型(包括 bool),依据标量值类型表 使用对应的C++类型替换int32。

Singular String Fields

对于任意这些字段的定义:

编译器将生成下列存取器方法:

  • bool has_foo() const: 如果字段被设置了返回 true。
  • const string& foo() const: 返回字段的当前值。如果字段没有被设置,返回缺省值。
  • void set_foo(const string& value): 设置字段的值。调用这个方法后,has_foo() 将返回 true,foo()返回 value 的一个副本(copy)。
  • void set_foo(const char* value): 采用C语言风格的以null结束的字符串设置字段的值。调用这个方法后,has_foo()返回 true,foo()返回 value 的一个副本(copy)。
  • void set_foo(const char* value, int size): 类似于上面,但是明确指定字符串大小而不是通过查找null终止字节决定。
  • string* mutable_foo(): 返回指向存储字段值的 string 对象的一个 mutable 指针。如果字段在调用这个方法之前没有被设置,那么返回的字符串将为空(而不是缺省值)。调用这个方法后,has_foo() 返回 true,foo() 返回被写入到字符串(foo)中的任何值。通过调用 Clear() 或 clear_foo() 清除此指针。
  • void clear_foo(): 清除字段的值。调用这个方法后,has_foo() 返回 false,foo()返回缺省值。
  • void set_allocated_foo(string* value): 赋值 string 对象给字段(foo),并且如果字段之前存在,释放它之前的值。如果 string 指针不为 NULL,此消息拥有分配的 string 对象的所有权(the message takes ownership of the allocated string object),然后 has_foo() 将返回 true。否则,如果 value 为 NULL,行为是与调用 clear_foo() 相同的。
  • string* release_foo(): 释放字段的所有权,然后返回 string 对象的指针。调用这个方法后,调用者获得分配的 string 对象的所有权(caller takes the ownership of the allocated string object),has_foo() 将返回 false,foo() 返回缺省值。

Singular Enum Fields

假定枚举类型为:

对于字段的这些定义中的任何一个:

编译器将生成下列存取器方法:

  • bool has_foo() const: 如果字段被设置返回 true。
  • Bar foo() const: 返回字段的当前值。如果字段没有被设置,返回缺省值。
  • void set_foo(Bar value): 设置字段的值。调用这个方法后,has_foo() 返回 true,foo()返回 value。在debug模式中(如,NDEBUG没有定义),如果 value 不匹配 Bar 中定义的任何值,此方法将忽略这个操作。
  • void clear_foo(): 清除字段的值。调用这个方法后,has_foo() 返回 false,foo()返回缺省值。

Singular Embedded Message Fields

假定消息类型为:

对于字段的这些定义中的任何一个:

  • bool has_foo() const: 如果字段被设置返回 true。
  • const Bar& foo() const: 返回字段的当前值。如果字段没有被设置,返回一个其中所有字段都被设置为none的 Bar (也许是 Bar::default_instance())。
  • Bar* mutable_foo(): 返回存储字段值得 Bar 对象的一个 mutable 指针。如果调用此方法前此字段没有被设置,那么将返回所有字段只为none的 Bar(例如,同新分配的 Bar 一样(it will be identical to a newly-allocated Bar))。调用这个方法后,has_foo() 将返回 true,foo()然会一个同 Bar 的实例一样的引用。通过调用 Clear() 或 clear_foo() 清除此指针。
  • void clear_foo(): 清除字段的值。调用这个方法后,has_foo() 返回 false, foo()返回缺省值。
  • void set_allocated_foo(Bar* bar): 赋值字段为 Bar 对象,并且如果此字段存在,清除字段之前的值。如果 Bar 指针不为 NULL,消息拥有分配的 Bar 对象的所有权(the message takes ownership of the allocated Bar object),然后 has_foo() 返回 true。否则,如果 Bar 为 NULL,行为是如同clear_foo()一样。
  • Bar* release_foo(): 释放字段的所有权,并且返回 Bar 对象指针。调用这个方法后,调用者获得分配的 Bar 对象的所有权(caller takes the ownership of the allocated Bar object),has_foo() 返回 false,foo()返回缺省值。

Repeated Numeric Fields

对于字段的这个定义:

编译器将生成下列存取器方法:

  • int foo_size() const: 返回字段中当前的元素数目。
  • int32 foo(int index) const: 返回给定索引处的元素值,索引以0开始。
  • void set_foo(int index, int32 value): 设置指定索引处的元素值,索引以0开始。
  • void add_foo(int32 value): 用给定的值为字段增加一个新的元素。
  • void clear_foo(): 从字段中移除所有元素。调用这个方法后,foo_size() 返回0.
  • const RepeatedField<int32>& foo() const: 返回存储字段元素的底层的 RepeatedField。此容器类提供类似于 STL 一样的迭代以及其他的方法。
  • RepeatedField<int32>* mutable_foo(): 返回指向存储字段元素的底层的RepeatedField的一个mutable指针。此容器类提供类似于 STL 一样的迭代以及其他的方法。

对于其他的数值字段类型(包括 bool),依据 标量值类型表 采用对应的C++类型替换int32。

Repeated String Fields

对于字段这些定义中的任何一个:

编译器将生成下列存取器方法:

  • int foo_size() const: 返回字段中当前的元素数目。
  • const string& foo(int index) const: 返回在指定索引处的元素,索引以0开始。
  • void set_foo(int index, const string& value): 设置指定索引处的元素的值,索引以0开始。
  • void set_foo(int index, const char* value): 采用C风格的以null为结束符的字符串设置指定索引处的元素值,索引以0开始。
  • void set_foo(int index, const char* value, int size): 类似于上面,但是明确给定字符串大小而不是由查找null结束符字节决定。
  • string* mutable_foo(int index): 返回存储指定索引处元素值的 string 对象的一个mutable指针。通过调用 Clear() 或 clear_foo()清除指针,或通过在某种程度上处理底层的RepeatedPtrField移除该元素。
  • void add_foo(const string& value): 用指定的值为字段增加一个元素。
  • void add_foo(const char* value): 用C风格的以null为结束符的字符串为字段增加一个元素。
  • void add_foo(const char* value, int size): 类似于上面,但是明确指定字符串的大小而不是通过查找null结束符字节来决定。
  • string* add_foo(): 添加一个新的空字符串元素,并返回一个指向它的指针。通过调用 Clear() 或 clear_foo() 清除此指针,或通过某种程度上处理底层的RepeatedPtrField移除该元素。
  • void clear_foo(): 从字段中移除所有元素。调用这个方法后,foo_size() 将返回0.
  • const RepeatedPtrField<string>& foo() const: 返回存储字段元素的底层的 RepeatedField。此容器类提供类似于 STL 一样的迭代以及其他的方法。
  • RepeatedPtrField<string>* mutable_foo(): 返回指向存储字段元素的底层的RepeatedField的一个mutable指针。此容器类提供类似于 STL 一样的迭代以及其他的方法。

Repeated Embedded Message Fields

假定如下消息类型:

对于字段的这个定义:

编译器将生成如下的存取器方法:

  • int foo_size() const: 返回字段中当前的元素数。
  • const Bar& foo(int index) const: 返回指定索引处的元素,索引以0开始。
  • Bar* mutable_foo(int index): 返回指向存储指定索引处元素值的 Bar 对象的一个 mutable 指针。通过调用 Clear() 或 clear_foo() 清除指针, 或者在某种程度上通过处理底层的 RepeatedPtrField 移除此元素
  • Bar* add_foo(): 添加一个新元素并且返回一个指向它的指针。返回的 Bar 所有的字段集为 none(如,它等同于一个新分配的 Bar (it will be identical to a newly-allocated Bar))。通过调用 Clear() 或 clear_foo() 清除指针, 或者在某种程度上通过处理底层的 RepeatedPtrField 移除此元素

官方文档地址: https://developers.google.com/protocol-buffers/docs/reference/cpp-generated , 

发表评论