Protobuf简单使用

C++ 生成代码指南 | 协议缓冲区文档 - ProtoBuf 中文

namespace

如果 .proto 文件包含 package 声明,则该文件的所有内容都将放置在相应的 C++ 命名空间中。例如,给定 package 声明

package foo.bar;

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

message

给定一个简单的消息声明

message Foo {}

协议缓冲区编译器生成一个名为 Foo 的类,该类公开派生自 google::protobuf::Message
Message 接口定义了允许您检查、操作、读取或写入整个消息的方法,包括从二进制字符串进行解析和序列化到二进制字符串。

  • bool ParseFromString(const string& data):从给定的序列化二进制字符串(也称为线格式)解析消息。
  • bool SerializeToString(string* output) const:将给定消息序列化为二进制字符串。
  • 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 的一个常量单例实例,它与 Foo 的新构造实例相同(因此所有奇数字段都未设置,所有重复字段都为空)。请注意,可以通过调用消息的 New() 方法将消息的默认实例用作工厂。

field

int

对于这两个字段定义

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

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

  • bool has_foo() const:如果设置了该字段,则返回 true
  • int32 foo() const:返回字段的当前值。如果未设置该字段,则返回默认值。
  • void set_foo(int32 value):设置字段的值。调用此方法后,has_foo() 将返回 truefoo() 将返回 value
  • void clear_foo():清除字段的值。调用此方法后,has_foo() 将返回 falsefoo() 将返回默认值。
repeat

对于此字段定义

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() 将返回零。
  • const RepeatedField<int32>& foo() const:返回存储字段元素的底层 RepeatedField。此容器类提供类似 STL 的迭代器和其他方法。
  • RepeatedField<int32>* mutable_foo():返回指向存储字段元素的底层可变 RepeatedField 的指针。此容器类提供类似 STL 的迭代器和其他方法。

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

string or bytes

对于这些字段定义

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():返回指向存储字段值的 string 可变对象的指针。如果在调用之前未设置字段,则返回的字符串将为空(不是默认值)。调用此项后,has_foo() 将返回 true,而 foo() 将返回写入给定字符串的任何值。
  • void clear_foo():清除字段的值。调用此方法后,has_foo() 将返回 falsefoo() 将返回默认值。
  • void set_allocated_foo(string* value):将 string 对象设置为字段,并在存在的情况下释放之前的字段值。如果 string 指针不是 NULL,则消息将获取已分配的 string 对象的所有权,并且 has_foo() 将返回 true。消息可以随时删除已分配的 string 对象,因此对该对象的引用可能会失效。否则,如果 valueNULL,则行为与调用 clear_foo() 相同。
  • string* release_foo():释放字段的所有权并返回 string 对象的指针。调用此项后,调用方将获取已分配的 string 对象的所有权,has_foo() 将返回 false,而 foo() 将返回默认值。
repeat

对于这两个字段定义

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

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

  • int foo_size() const:返回字段中当前的元素数量。要检查空集,请考虑使用底层 RepeatedField 中的 empty() 方法,而不是此方法。
  • const string& foo(int index) 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):返回指向可变 string 对象的指针,该对象存储给定基于零的索引处的元素的值。使用 [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() 将返回零。
  • const RepeatedPtrField<string>& foo() const:返回存储该字段元素的底层 RepeatedPtrField。此容器类提供类似 STL 的迭代器和其他方法。
  • RepeatedPtrField<string>* mutable_foo():返回存储该字段元素的底层可变 RepeatedPtrField 的指针。此容器类提供类似 STL 的迭代器和其他方法。

embed message

给定消息类型

message Bar {}

对于这些字段定义

//proto2
optional Bar foo = 1;
required Bar foo = 1;

//proto3
Bar foo = 1;

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

  • bool has_foo() const:如果设置了该字段,则返回 true
  • const Bar& foo() const:返回字段的当前值。如果字段未设置,则返回一个未设置任何字段的 Bar(可能是 Bar::default_instance())。
  • Bar* mutable_foo():返回指向存储字段值的 Bar 可变对象的指针。如果在调用之前未设置字段,则返回的 Bar 将未设置任何字段(即它将与新分配的 Bar 相同)。调用此方法后,has_foo() 将返回 truefoo() 将返回对 Bar 相同实例的引用。
  • void clear_foo():清除字段的值。调用此方法后,has_foo() 将返回 falsefoo() 将返回默认值。
  • void set_allocated_foo(Bar* bar):将 Bar 对象设置为字段,并在存在的情况下释放之前的字段值。如果 Bar 指针不为 NULL,则消息将获取已分配 Bar 对象的所有权,has_foo() 将返回 true。否则,如果 BarNULL,则行为与调用 clear_foo() 相同。
  • Bar* release_foo():释放字段的所有权并返回 Bar 对象的指针。调用此方法后,调用方获取已分配 Bar 对象的所有权,has_foo() 将返回 falsefoo() 将返回默认值。
repeat

给定消息类型

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() 将返回零。
  • const RepeatedPtrField<Bar>& foo() const:返回存储该字段元素的底层 RepeatedPtrField。此容器类提供类似 STL 的迭代器和其他方法。
  • RepeatedPtrField<Bar>* mutable_foo():返回指向存储字段元素的底层可变 RepeatedPtrField 的指针。此容器类提供类似 STL 的迭代器和其他方法。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Protocol Buffers(简称 Protobuf)是一种语言无关、平台无关、可扩展的序列化数据格式,它可以用于数据存储、通信协议等领域。Protobuf 是 Google 公司开发的,它的主要优点是高效、轻量、可扩展。 下面是 Protobuf 的详细使用方法: 1. 安装 Protobuf 首先,需要安装 Protobuf 编译器。可以从官网下载安装包,也可以使用包管理工具进行安装。以下是在 Ubuntu 上使用 apt-get 进行安装的示例: ``` $ sudo apt-get install protobuf-compiler ``` 2. 定义 Protobuf 文件 Protobuf 使用 .proto 文件来定义数据结构。以下是一个简单的示例: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; repeated string email = 3; } ``` 上面的示例定义了一个名为 Person 的消息类型,它包含三个字段:name、age 和 email。其中,name 和 age 是必需的字段,而 email 是可重复的字段。 3. 编译 Protobuf 文件 使用 Protobuf 编译器将 .proto 文件编译成目标语言的代码。以下是在 Linux 上使用命令行编译的示例: ``` $ protoc --proto_path=./proto --cpp_out=./src ./proto/person.proto ``` 上面的示例将 ./proto 目录下的 person.proto 文件编译成 C++ 代码,并将生成的代码存放在 ./src 目录下。 4. 序列化和反序列化 使用生成的代码进行序列化和反序列化操作。以下是一个示例: ```c++ #include "person.pb.h" #include <iostream> #include <fstream> using namespace std; int main() { // 创建一个 Person 对象 Person person; person.set_name("Tom"); person.set_age(20); person.add_email("tom@example.com"); person.add_email("tom@gmail.com"); // 将 Person 对象序列化到文件中 fstream output("person.bin", ios::out | ios::binary); person.SerializeToOstream(&output); output.close(); // 从文件中读取序列化的 Person 对象 fstream input("person.bin", ios::in | ios::binary); Person person2; person2.ParseFromIstream(&input); input.close(); // 输出读取到的 Person 对象的信息 cout << "name: " << person2.name() << endl; cout << "age: " << person2.age() << endl; for (int i = 0; i < person2.email_size(); i++) { cout << "email: " << person2.email(i) << endl; } return 0; } ``` 上面的示例将创建一个 Person 对象,并将其序列化到文件中。然后,从文件中读取序列化的 Person 对象,并输出其信息。 以上就是 Protobuf 的详细使用方法。需要注意的是,每个目标语言的生成代码可能会有所不同。因此,在使用 Protobuf 时,需要查看官方文档,了解相关的生成代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值