本系列文章将通过对通讯录项目的不断完善,带大家由浅入深的学习Protobuf的使用。这是Contacts的2.2版本,在这篇文章中将带大家学习Protobuf的 Any 类型语法,并将其用到我们的项目中
Protobuf中的Any类型可以理解为泛型类型,它可以存储任何消息类型的字段(int, char等类型必须先封装成消息类型)。Any类型字段也可以用 Repeated
修饰。
Any类型定义在 any.proto 文件中。可以在 /usr/local 路径下可以找到。我在安装的时候将 lib 和 include 统一配置到 /usr/local/protobuf 文件中。如果没有配置的话,lib和include是分散的。
①头文件的包含:
使用Any字段前首先需要包含头文件,先前做过的环境变量配置如上
②命名空间:gooole::protobuf
我们先创建一个Address消息字段,并在 PeopleInfo 消息中用Any类型字段接收
syntax = "proto3";
package contact2;
import "google/protobuf/any.proto";
message Address{
string home = 1;
string company = 2;
}
message PeopleInfo{
string name = 1;
int32 age = 2;
message Phone{
string number = 1;
enum PhoneType{
MOBILE = 0;
FIXED = 1;
}
PhoneType type = 2;
}
repeated Phone phone = 3;
google.protobuf.Any addr = 4;
}
message Contact{
repeated PeopleInfo contact = 1;
}
编译 .proto 文件后,我们来分析 contacts.pb.h 文件中对于Any类型更新的代码片段
// [作用]:判断Any字段addr是否被设置
bool has_addr() const;
// [作用]:清除对Any字段的设置(重置为默认值)
void clear_addr();
// [作用]:返回Any字段的内容
const ::PROTOBUF_NAMESPACE_ID::Any& addr() const;
// [作用]:用于获取Any消息中的 addr 成员变量,并返回一个指向 addr 的指针,可以通过这个指针修改该Any对象中 addr
::PROTOBUF_NAMESPACE_ID::Any* mutable_addr();
// [注意]:在使用 mutable_addr() 方法获取指针之前,需要确定该 Any 字段中存储的值已经被正确地解析为具体的类型,否则直接使用 mutable_addr() 可能会导致程序崩溃或者其他不可预知的问题
// [作用]:释放 Any 对象中包含的数据(Any字段里的内容被重置为默认值),并返回一个指向释放数据的指针。也就是将该对象的所有权转移给调用方
PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Any* release_addr();
// [注意]:该方法所释放的是 Any 类型对象中存储的对象的所有权,而非 Any 类型对象本身的所有权。
前面提到,Any字段中可以存储任意消息类型,这就要涉及到任意消息类型和Any类型的互转。这部分代码就在Google为我们写好的头文件 any.pb.h 中。
// 将任意消息类型转为Any类型
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message)
// 将Any类型转为任意消息类型
bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const
// 判断 Any 字段存储的对象类型是否为 T
template<typename T> bool Is() const
read.cc:
区分下面的写法:
[说明]:
- 正确:addr返回的是const对象。const对象才能调用const修改的函数
- 错误:mutable_addr的对象是可以修改