文章目录
- 前言
- 使用示例
- 定义message结构
- 结构体赋值
- ByteSizeLong()
- GetTypeName()
- DebugString()
- ShortDebugString()
- CopyFrom(const MessageLite& other)
- Clear()
- Ohters
- 总结
前言
游戏项目中使用protobuf作为双端协议通讯的方式,算是一种中规中矩的方法了,偶尔会需要查看序列化后的消息占用空间大小,一直都是用序列化后的字符串来查看,即使临时测试一个结构占用空间也要序列化后才能调用 .size()
函数,最近偶然间发现有个 ByteSizeLong()
可直接用于BP结构上,这倒是简单了一点点,所以把常用的几个函数列举总结一下,免的自己时间太长忘记了。
使用示例
定义message结构
在调用函数之前先定义一个结构文件吧
syntax = "proto3";
package ProtoMsg;
option go_package = "./;ProtoMsg";message Address { // 地址结构string city = 1;string street = 2;
}message Person {int32 age = 1; // 年龄string name = 2; // 姓名bool student = 3; // 学生Address address = 4; // 地址map<string, string> tags = 5; // 标签信息repeated int64 lucky_nums = 6; // 幸运数字
}
结构体赋值
接着我们使用C++语言给这个结构赋值,然后尝试在此基础上调用不同的函数
ProtoMsg::Person person;person.set_age(18);person.set_name("albert");person.set_student(true);person.mutable_address()->set_city("beijing");person.mutable_address()->set_street("soho");(*person.mutable_tags())["hobby"] = "reading";(*person.mutable_tags())["family"] = "warm";person.add_lucky_nums(1);person.add_lucky_nums(9);
ByteSizeLong()
这是一个获取protobuf结构大小的函数,起初我找到的是 ByteSize()
,但是这个函数返回值是int,现在已经不建议使用了,所以之后请直接使用 ByteSizeLong()
来获取结构大小,就像下面这样:
std::cout << "show person size [" << person.ByteSizeLong() << "] and address size [" << person.address().ByteSizeLong() << "].";// 输出结果
// show person size [67] and address size [15].
GetTypeName()
这个函数可以获取结构的名字,有一点点元数据的意思,在输出日志时可以使内容更清晰:
std::cout << "show person type name [" << person.GetTypeName() << "] and address type name [" << person.address().GetTypeName() << "].";// 输出结果
// show person type name [ProtoMsg.Person] and address type name [ProtoMsg.Address].
DebugString()
这个函数看名字就知道和调试信息有关,它可以打印整个结构的数据:
std::cout << "show person debug string [" << person.DebugString() << "]."// 输出结果
// show person debug string [age: 18
// name: "albert"
// student: true
// address {
// city: "beijing"
// street: "soho"
// }
// lucky_nums: 1
// lucky_nums: 9
// tags {
// key: "family"
// value: "warm"
// }
// tags {
// key: "hobby"
// value: "reading"
// }
// ].
ShortDebugString()
我们发现 DebugString()
输出的内容换行较多,虽然看起来更清晰,但是不便于存入日志按行查找,要想存储日志文件中,ShortDebugString()
函数是更好的选择:
std::cout << "show person short debug string [" << person.ShortDebugString() << "].";// 输出结果
// show person short debug string [age: 18 name: "albert" student: true address { city: "beijing" street: "soho" } lucky_nums: 1 lucky_nums: 9 tags { key: "family" value: "warm" } tags { key: "hobby" value: "reading" }].
CopyFrom(const MessageLite& other)
这个结构用于结构的拷贝,比如你已经有了一个地址结构对象,再创建新的 Person
时就不必对address字段一一赋值,而是可以直接使用CopyFrom函数完成:
ProtoMsg::Address addr;addr.set_city("shanghai");addr.set_street("nanjinglu");person.mutable_address()->CopyFrom(addr);std::count << "show person short debug string [" << person.ShortDebugString() << "].";// 输出结果
// show person short debug string [age: 18 name: "albert" student: true address { city: "shanghai" street: "nanjinglu" } lucky_nums: 1 lucky_nums: 9 tags { key: "family" value: "warm" } tags { key: "hobby" value: "reading" }].
Clear()
清空当前消息的所有字段,重置为默认状态,这个我倒是不太常用,但是测试时偶尔会用到:
person.Clear();std::cout << "show person size [" << person.ByteSizeLong() << "] and short debug string [" << person.ShortDebugString() << "].";// 输出结果
// show person size [0] and short debug string [].
Ohters
其他还有一些函数属于使用protobuf的常见函数,我就不再举例了,简单列举下函数作用:
MergeFrom(const MessageLite& other)
合并另一个消息的内容到当前消息中(可能会覆盖现有字段)SerializeToString(std::string* output)
将消息序列化为字符串格式,并将结果存储在提供的 std::string 对象中ParseFromString(const std::string& data)
从给定的字符串解析出消息数据std::string SerializeAsString() const
将消息序列化为字符串格式并返回bool SerializeToArray(void* data, int size) const
直接将消息序列化到用户提供的缓冲区中google::protobuf::MessageLite::ParseFromArray(const void *data, int size)
将给定的二进制数据解析为 Protocol Buffers 消息对象
总结
ByteSizeLong()
可以用来获取一个protobuf结构的大小GetTypeName()
可以用来返回一个结构的名字ShortDebugString()
可以用返回一个结构的数据内容protobuf
这种经典的开源库挖一挖总会有惊喜
慢就是快,每个人都有不同的解读,曾经有那么两次我好像都能顿悟了,可思绪闪现了那么一刻就消失了;稳稳地慢是幸运的,最近总是听人讲到控制回撤这个词,尽管他喊得声嘶力竭,起初我却不以为意,但经历的多了以后开始理解他所说的价值,才理解慢慢变富的含义,既然是概率游戏,只要能保证胜率在51%,那么最后一定会赢的,我们要做的只是按照自己的节奏不断地重复,不断地重复就好~