3-protocol buffer c++生成代码指南

    当使用--cpp_out=命令行标志调用时,protocol buffer 编译器产生c++输出。--cpp_out=选项的参数是您希望编译器在其中编写c++输出的目录。编译器为每个.proto文件输入创建一个头文件和一个实现文件。输出文件的名称是通过获取.proto文件的名称并进行以下更改来计算的:

    扩展名(.proto)被.pb.h或.pb替换。分别为头文件或实现文件。
    proto路径(用--proto_path=或-I命令行标志指定)被输出路径(用--cpp_out=标志指定)替换。
例如,假设你像下面这样调用编译器:

protoc --proto_path=src --cpp_out=build/gen src/foo.proto src/bar/baz.proto

    编译器将读取src/foo.proto和src/bar/baz.proto生成四个输出文件:build/gen/foo.pb.h, build/gen/foo.pb.cc, build/gen/bar/baz.pb.h, build/gen/bar/baz.pb.cc。如果需要,编译器会自动创建build/gen/bar目录,但它不会创建build或build/gen;它们必须已经存在。

Packages

    如果.proto文件包含包声明,则文件的整个内容将被放置在相应的c++命名空间中。例如,给定包声明:

package foo.bar;

    文件中的所有声明都将驻留在foo::bar命名空间中。

Messages

     给出一个简单的消息声明:

message Foo {}

    protocol buffer编译器生成一个名为Foo的类,它public派生自google::protobuf::Message。类是一个具体类,没有未实现的纯虚方法。默认情况下,Foo实现所有方法的专用版本以获得最大速度。但是,如果.proto文件包含以下行:

option optimize_for = CODE_SIZE;

    那么Foo将只覆盖功能所需的最小方法集,这大大减少了生成代码的大小,但也降低了性能。或者,如果.proto文件包含:

option optimize_for = LITE_RUNTIME;

    那么Foo将包括所有方法的快速实现,但将实现google::protobuf::MessageLite接口,该接口只包含Message方法的一个子集。特别是,它不支持描述符或反射。但是,在这种模式下,生成的代码只需要链接到libprotobuf-lite。(libprotobuf-lite。libprotobuf (Windows上的libprotobuf)。(libprotobuf.lib)。“精简”库比完整库小得多,更适合于资源受限的系统。

    不应该创建自己的Foo子类。如果创建该类的子类并重写虚拟方法,则重写可能会被忽略,因为许多生成的方法调用被去虚拟化以提高性能。

    Message接口定义了一些方法,这些方法允许您检查、操作、读取或写入整个消息,包括解析二进制字符串和序列化二进制字符串。

    1.bool ParseFromString(const string& data):从给定的序列化二进制字符串(也称为有线格式)中解析消息。

    2.bool SerializeToString(string* output) const:将给定的消息序列化为二进制字符串。

    3. string DebugString():返回一个字符串,给出原型的text_format表示形式(应该只用于调试)。

    除了这些方法,Foo类还定义了以下方法:

    Foo():默认构造函数。
    ~Foo():默认析构函数。
    Foo(const Foo& other):复制构造函数。
    Foo(Foo&& other):移动构造函数。
    Foo& operator=(const Foo& other):赋值操作符。
    Foo& operator=(Foo&& other):移动赋值操作符。
    void Swap(Foo* other):用另一条消息交换内容。
    const UnknownFieldSet& unknown_fields() const:返回解析此消息时遇到的未知字段集。如果在.proto文件中指定了option optimize_for = LITE_RUNTIME,则返回类型更改为std::string&。
    UnknownFieldSet* mutable_unknown_fields():返回一个指针,指向解析此消息时遇到的未知字段的可变集。如果在.proto文件中指定了option optimize_for = LITE_RUNTIME,则返回类型更改为std::string*。

    该类还定义了以下静态方法:

    static const Descriptor* Descriptor():返回类型的描述符。这包含关于类型的信息,包括它有哪些字段以及它们的类型。
    static const Foo& default_instance():返回Foo的const单例实例,该实例与新建的Foo实例相同。请注意,message的默认实例可以通过调用其New()方法作为工厂使用。

生成的文件名

    保留关键字在生成的输出中以下划线追加。

    例如,下面的proto3定义语法:

message MyMessage {
  string false = 1;
  string myFalse = 2;
}

    生成以下部分输出:

  void clear_false_() ;
  const std::string& false_() const;
  void set_false_(Arg_&& arg, Args_... args);
  std::string* mutable_false_();
  PROTOBUF_NODISCARD std::string* release_false_();
  void set_allocated_false_(std::string* ptr);

  void clear_myfalse() ;
  const std::string& myfalse() const;
  void set_myfalse(Arg_&& arg, Args_... args);
  std::string* mutable_myfalse();
  PROTOBUF_NODISCARD std::string* release_myfalse();
  void set_allocated_myfalse(std::string* ptr);

嵌套类型

    一条消息可以在另一条消息中声明。例如:

message Foo {
  message Bar {}
}

    在这种情况下,编译器生成两个类:Foo和Foo_Bar。此外,编译器在Foo内部生成一个typedef,如下所示:

typedef Foo_Bar Bar;

    这意味着您可以像使用嵌套类Foo::Bar一样使用嵌套类型的类。但是,请注意c++不允许前向声明嵌套类型。如果你想在另一个文件中向前声明Bar并使用该声明,你必须将其标识为Foo_Bar。

字段

    除了上一节中描述的方法之外,protocol buffer编译器还为.proto文件中消息中定义的每个字段生成一组访问器方法,比如has_foo()和clear_foo()。

    除了访问器方法外,编译器还为每个包含其字段号的字段生成一个整数常量。常量名是字母k,后面跟着转换成驼峰大小写的字段名,后面跟着FieldNumber。例如,给定可选字段int32 foo_bar = 5;,编译器将生成常量static const int kFooBarFieldNumber = 5;

Optional数字字段(proto2和proto3)

    对于这两个字段的定义:

optional int32 foo = 1;
required int32 foo = 1;

    编译器将生成以下访问器方法:

    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), int32将根据标量值类型表替换为相应的c++类型。

Optional  String/Bytes字段(proto2和proto3)

    对于任何这些字段定义:

optional string foo = 1;
required string foo = 1;
optional bytes foo = 1;
required bytes foo = 1;

    编译器将生成以下访问器方法:

    bool has_foo() const:如果设置了该字段,则返回true。
    const string& foo() const:返回字段的当前值。如果未设置该字段,则返回默认值。
    void set_foo(const string& value):设置字段的值。调用此函数后,has_foo()将返回true, foo()将返回value的副本。
    void set_foo(string&& value) (c++ 11及以上版本):设置字段的值,从传递的字符串开始移动。调用此函数后,has_foo()将返回true, foo()将返回value的副本。
    void set_foo(const char* value):使用c风格的以空结尾的字符串设置字段的值。调用此函数后,has_foo()将返回true, foo()将返回value的副本。
    void set_foo(const char* value, int size):和上面一样,但是字符串的大小是显式给出的,而不是通过查找空结束符字节来确定的。
    string* mutable_foo():返回一个指向可变字符串对象的指针,该对象存储字段的值。如果在调用之前没有设置该字段,那么返回的字符串将为空(不是默认值)。调用此函数后,has_foo()将返回true,而foo()将返回写入给定字符串的任何值。
    void clear_foo():清除字段的值。调用此函数后,has_foo()将返回false,而foo()将返回默认值。
void set_allocated_foo(string* value):将字符串对象设置为字段,如果存在则释放前一个字段的值。如果字符串指针不为NULL,则消息获取分配的字符串对象的所有权,并且has_foo()将返回true。消息可以随时删除分配的字符串对象,因此对该对象的引用可能无效。否则,如果值为NULL,则行为与调用clear_foo()相同。
    string* release_foo():释放字段的所有权并返回字符串对象的指针。调用this之后,调用者获得分配的字符串对象的所有权,has_foo()将返回false, foo()将返回默认值。

Optional 枚举字段(proto2、proto3)

    给定枚举类型:

enum Bar {
  BAR_UNSPECIFIED = 0;
  BAR_VALUE = 1;
  BAR_OTHER_VALUE = 2;
}

    对于这两个字段的定义:

optional Bar foo = 1;
required Bar foo = 1;

    编译器将生成以下访问器方法:

    bool has_foo() const:如果设置了该字段,则返回true。
    Bar foo() const:返回字段的当前值。如果未设置该字段,则返回默认值。
    void set_foo(Bar value):设置字段的值。调用此函数后,has_foo()将返回true, foo()将返回value。在调试模式下(即未定义NDEBUG),如果value与为Bar定义的任何值不匹配,则此方法将中止该进程。
    void clear_foo():清除字段的值。调用此函数后,has_foo()将返回false,而foo()将返回默认值。

repeated数值字段

    对于这个字段的定义:

repeated int32 foo = 1;

    int foo_size() const:返回字段中当前元素的数量。要检查空集,请考虑在底层RepeatedField中使用empty()方法,而不是使用此方法。
    int32 foo(int index) const:返回给定从零开始的索引处的元素。使用索引不在[0,foo_size())的方法调用此方法会产生未定义的行为。
    void set_foo(int index, int32 value):设置元素在给定的从零开始的索引处的值。
    void add_foo(int32 value):在给定值的字段末尾添加一个新元素。
    void clear_foo():从字段中删除所有元素。调用此函数后,foo_size()将返回0。
    const RepeatedField<int32>& foo() const:返回存储字段元素的底层RepeatedField。这个容器类提供了类似stl的迭代器和其他方法。
    RepeatedField<int32>* mutable_foo():返回一个指向存储字段元素的底层可变RepeatedField的指针。这个容器类提供了类似stl的迭代器和其他方法。

repeated字符串字段

    对于这两个字段的定义:

repeated string foo = 1;
repeated bytes foo = 1;


    编译器将生成以下访问器方法:

    int foo_size() const:返回字段中当前元素的数量。要检查空集,请考虑在底层RepeatedField中使用empty()方法,而不是使用此方法。
const:返回给定从零开始的索引处的元素。在索引不在[0,foo_size()-1]的情况下调用此方法会产生未定义的行为。
    void set_foo(int index, const string& value):设置元素在给定的从零开始的索引处的值。
    void set_foo(int index, const char* value):使用c风格的以空结尾的字符串设置给定的从零开始的索引处的元素的值。
    void set_foo(int index, const char* value, int size):和上面一样,但是字符串的大小是显式给出的,而不是通过查找空结束符字节来确定的。
    string* mutable_foo(int index):返回一个指向可变字符串对象的指针,该对象存储在给定从零开始的索引处的元素的值。使用索引不在[0,foo_size())的方法调用此方法会产生未定义的行为。
    void add_foo(const string& value):在给定值的字段末尾添加一个新元素。
    void add_foo(const char* value):使用c风格的以空结尾的字符串在字段的末尾追加一个新元素。
    void add_foo(const char* value, int size):和上面一样,但是字符串的大小是显式给出的,而不是通过查找空结束符字节来确定的。
    string* add_foo():在字段的末尾添加一个新的空字符串元素,并返回一个指向它的指针。
    void clear_foo():从字段中删除所有元素。调用此函数后,foo_size()将返回0。
    const RepeatedPtrField<string>& foo() const:返回存储字段元素的底层RepeatedPtrField。这个容器类提供了类似stl的迭代器和其他方法。
    RepeatedPtrField<string>* mutable_foo():返回一个指向存储字段元素的底层可变            RepeatedPtrField的指针。这个容器类提供了类似stl的迭代器和其他方法。

repeated枚举字段

    给定枚举类型:

enum Bar {
  BAR_UNSPECIFIED = 0;
  BAR_VALUE = 1;
  BAR_OTHER_VALUE = 2;
}

    对于这个字段的定义:

repeated Bar foo = 1;

    编译器将生成以下访问器方法:

    int foo_size() const:返回字段中当前元素的数量。要检查空集,请考虑在底层RepeatedField中使用empty()方法,而不是使用此方法。
    Bar foo(int index) const:返回给定从零开始的索引处的元素。使用索引不在[0,foo_size())的方法调用此方法会产生未定义的行为。
    void set_foo(int index, Bar value):设置元素在给定的从零开始的索引处的值。在调试模式下(即未定义NDEBUG),如果value与为Bar定义的任何值不匹配,则此方法将中止该进程。
    void add_foo(Bar value):在给定值的字段末尾添加一个新元素。在调试模式下(即未定义NDEBUG),如果value与为Bar定义的任何值不匹配,则此方法将中止该进程。
    void clear_foo():从字段中删除所有元素。调用此函数后,foo_size()将返回0。
const RepeatedField<int>& foo() const:返回存储字段元素的底层RepeatedField。这个容器类提供了类似stl的迭代器和其他方法。
    RepeatedField<int>* mutable_foo():返回一个指向存储字段元素的底层可变RepeatedField的指针。这个容器类提供了类似stl的迭代器和其他方法。

repeated嵌入消息字段

    给定消息类型:

message Bar {}

    对于这个字段的定义:

repeated Bar foo = 1;

    编译器将生成以下访问器方法:

    int foo_size() const:返回字段中当前元素的数量。要检查空集,请考虑在底层RepeatedField中使用empty()方法,而不是使用此方法。
    const Bar& foo(int index) const:返回给定从零开始索引的元素。使用索引不在[0,foo_size())的方法调用此方法会产生未定义的行为。
    Bar* mutable_foo(int index):返回一个指向可变Bar对象的指针,该对象存储在给定的从零开始的索引处的元素值。使用索引不在[0,foo_size())的方法调用此方法会产生未定义的行为。
    Bar* add_foo():在字段的末尾添加一个新元素并返回一个指向它的指针。返回的Bar是可变的,不会设置任何字段(也就是说,它将与新分配的Bar相同)。
    void clear_foo():从字段中删除所有元素。调用此函数后,foo_size()将返回0。
    const RepeatedPtrField<Bar>& foo() const:返回存储字段元素的底层RepeatedPtrField。这个容器类提供了类似stl的迭代器和其他方法。
    RepeatedPtrField<Bar>* mutable_foo():返回一个指向存储字段元素的底层可变RepeatedPtrField的指针。这个容器类提供了类似stl的迭代器和其他方法。

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值