Protobuf, understand the hood
proto文件定义
package lm;
message Foo{
required int32 id = 1;
}
message Bar{
required int32 id = 1 [default = 12];
required string str= 2 [default = "bar::str"];
required Foo foo= 3;
}
下面分析protoc编译生成的:ph.b和pb.cc文件。
初始化
protoc会定义一个全局对象:
struct StaticDescriptorInitializer_lm_2ehelloworld_2eproto {
StaticDescriptorInitializer_lm_2ehelloworld_2eproto() {
protobuf_AddDesc_lm_2ehelloworld_2eproto();
};
} static_descriptor_initializer_lm_2ehelloworld_2eproto_;
其中protobuf_AddDesc_lm_2ehelloworld_2eproto()函数完成了默认值的初始化:
void protobuf_AddDesc_lm_2ehelloworld_2eproto() {
static bool already_here = false;
...
Foo::default_instance_ = new Foo();
Bar::_default_str_ =
new ::std::string("bar::str", 8); // string默认值存在这里
Bar::default_instance_ = new Bar();
Foo::default_instance_->InitAsDefaultInstance();
Bar::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_lm_2ehelloworld_2eproto);
}
同时注册了清理函数protobuf_ShutdownFile_lm_2ehelloworld_2eproto:
void protobuf_ShutdownFile_lm_2ehelloworld_2eproto() {
delete Foo::default_instance_;
delete Foo_reflection_;
delete Bar::default_instance_;
delete Bar_reflection_;
delete Bar::_default_str_;
}
构造
默认值的赋值在构造函数里:
Bar::Bar()
: ::google::protobuf::Message() {
SharedCtor();
// @@protoc_insertion_point(constructor:lm.Bar)
}
void Bar::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
id_ = 12; // id默认值
str_ = const_cast< ::std::string*>(_default_str_); // str默认值
foo_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
整数标示符的名称为kXxxFieldNumber:
class Bar : public ::google::protobuf::Message {
public:
static const int kIdFieldNumber = 1;
static const int kStrFieldNumber = 2;
static const int kFooFieldNumber = 3;
};
析构
新建的对象在析构函数里删除:
Bar::~Bar() {
// @@protoc_insertion_point(destructor:lm.Bar)
SharedDtor();
}
void Bar::SharedDtor() {
if (str_ != _default_str_) {
delete str_;
}
if (this != default_instance_) {
delete foo_;
}
};
Mutable Pointer
使用mutable_xxx()时,如果没有set过,则new一个新对象出来返回:
inline ::std::string* Bar::mutable_str() {
set_has_str();
if (str_ == _default_str_) {
str_ = new ::std::string(*_default_str_);
}
return str_;
}
inline ::lm::Foo* Bar::mutable_foo() {
set_has_foo();
if (foo_ == NULL) foo_ = new ::lm::Foo;
return foo_;
}
Allocate Value
使用set_allocated_xxx()时,清理掉原来的对象,用新对象赋值:
inline void Bar::set_allocated_str(::std::string* str) {
if (str_ != _default_str_) {
delete str_;
}
if (str) {
set_has_str();
str_ = str;
} else {
clear_has_str();
str_ = const_cast< ::std::string*>(_default_str_);
}
}
inline void Bar::set_allocated_foo(::lm::Foo* foo) {
delete foo_;
foo_ = foo;
if (foo) {
set_has_foo();
} else {
clear_has_foo();
}
}
Clear
Clear()时重设为默认值:
void Bar::Clear() {
if (_has_bits_[0 / 32] & 7) {
id_ = 12;
if (has_str()) {
if (str_ != _default_str_) {
str_->assign(*_default_str_);
}
}
if (has_foo()) {
if (foo_ != NULL) foo_->::lm::Foo::Clear();
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->Clear();
}
从这里面看出,只是重新赋值,如果是allocated的值,不会清理,所以需要allocate的人自己管理内存。
Protobuf, understand the hood的更多相关文章
- UNDER THE HOOD OF THE NEW AZURE PORTAL
http://jbeckwith.com/2014/09/20/how-the-azure-portal-works/ So - I haven’t been doing much blogging ...
- [under the hood]Reduce EXE and DLL Size with LIBCTINY.LIB
Matt Pietrek Download the code for this article: Hood0101.exe (45KB) W ay back in my October 1996 co ...
- C++ Under the Hood
The original article is taken from http://msdn.microsoft.com/archive/en-us/dnarvc/html/jangrayhood.a ...
- under the hood
under the hood adjective a metaphorical area that contains the underlying implementation of somethin ...
- C++操作Kafka使用Protobuf进行跨语言数据交互
C++操作Kafka使用Protobuf进行跨语言数据交互 Kafka 是一种分布式的,基于发布 / 订阅的消息系统.主要设计目标如下: 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 T ...
- python通过protobuf实现rpc
由于项目组现在用的rpc是基于google protobuf rpc协议实现的,所以花了点时间了解下protobuf rpc.rpc对于做分布式系统的人来说肯定不陌生,对于rpc不了解的童鞋可以自行g ...
- Protobuf使用规范分享
一.Protobuf 的优点 Protobuf 有如 XML,不过它更小.更快.也更简单.它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍.你可以定义自己的数据结构 ...
- java netty socket库和自定义C#socket库利用protobuf进行通信完整实例
之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...
- 在Wcf中应用ProtoBuf替代默认的序列化器
Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...
随机推荐
- mysql 主从搭建
主要搭建步骤如下: 1.打开binlog,设置server_id 打开主库的--log-bin,并设置server_id 2.主库授权 --最好也在从库对主库授权 ...
- .net转php laraval框架学习系列(二)项目实战---Models
上一篇已经介绍开发环境的搭建,如果有问题可以在文章后留言. 这篇将从项目实战开发,一步一步了解laravel框架. 在开发mvc项目时,models都是第一步. 下面就从建模开始. 实体关系图 由于不 ...
- Oracle 存储过程,临时表,动态SQL测试
--创建事务级别的结果临时表 create global temporary table tmp_yshy( c1 ), c2 ) )on commit delete rows; --创建事务级别的存 ...
- 将rcc.exe添加到系统Path
rcc不是内部或外部命令搜索下rcc.exe二进制文件的位置,然后将该路径添加到path环境变量中. 在cmd中输入path,显示当前的环境变量. 然后path = %path%;C:\Qt\4.8. ...
- java decompiler如何去掉行号
今天想反编译jar包保存源代码,默认前面加了行号,不知道这个小工具如何设置去掉行号? 反编译后: 找到它的安装路径,我的是:C:\Program Files\decomp.然后将该路径加入到环境变量p ...
- ImageButton自定义按钮的按下效果的高效实现方法(非一般)
通常情况下,我们可以采用如下方式实现: <?xml version="1.0" encoding="UTF-8"?> <selector xm ...
- bzoj4005[JLOI2015]骗我呢
http://www.lydsy.com/JudgeOnline/problem.php?id=4005 神题~远距离orz 膜拜PoPoQQQ大神 #include<cstdio> #i ...
- poj2689:素数筛
题目大意,给定l和u,求区间[l,u]内的素数中,相邻两个差最大和最小的素数其中 u的范围达到了2e9本质上需要找出n以内的所有素数,使用筛法.先保存50000(大于sqrt(2e9))内的所有素数, ...
- HDU5584 LCM Walk 数论
LCM Walk Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- Java:单例模式的七种写法[转]
第一种(懒汉,线程不安全): 1 public class Singleton { 2 private static Singleton instance; 3 privat ...