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的更多相关文章

  1. 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 ...

  2. [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 ...

  3. C++ Under the Hood

    The original article is taken from http://msdn.microsoft.com/archive/en-us/dnarvc/html/jangrayhood.a ...

  4. under the hood

    under the hood adjective a metaphorical area that contains the underlying implementation of somethin ...

  5. C++操作Kafka使用Protobuf进行跨语言数据交互

    C++操作Kafka使用Protobuf进行跨语言数据交互 Kafka 是一种分布式的,基于发布 / 订阅的消息系统.主要设计目标如下: 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 T ...

  6. python通过protobuf实现rpc

    由于项目组现在用的rpc是基于google protobuf rpc协议实现的,所以花了点时间了解下protobuf rpc.rpc对于做分布式系统的人来说肯定不陌生,对于rpc不了解的童鞋可以自行g ...

  7. Protobuf使用规范分享

    一.Protobuf 的优点 Protobuf 有如 XML,不过它更小.更快.也更简单.它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍.你可以定义自己的数据结构 ...

  8. java netty socket库和自定义C#socket库利用protobuf进行通信完整实例

    之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...

  9. 在Wcf中应用ProtoBuf替代默认的序列化器

    Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...

随机推荐

  1. HTML&CSS基础学习笔记1.3-HTML的标签语法

    HTML标签语法 1. 标签由英文尖括号<和>括起来,如<html>就是一个标签. 2. HTML中的标签一般都是成对出现的,分开始标签和结束标签.结束标签比开始标签多了一个/ ...

  2. C程序设计语言练习题1-12

    练习1-12 编写一个程序,以每行一个单词的行驶打印其输入. 代码如下: #include <stdio.h> // 包含标准库的信息. int main() // 定义名为main的函数 ...

  3. canvas个人总结

    今天做了大量的canvas作业,发现很多的步奏都是一样的,我自己就封装了一个画直线形2D图形函数.功能不是很强大. function drawModule(Json,strokeStyle,fillS ...

  4. Hdu1097(计算a的b次幂最后一位数值)

    #include <stdio.h> #include <math.h> int main() { int Num1,Num2; while(scanf("%d %d ...

  5. oracle 主键应用序列和触发器实现自动增长

    oracle 主键自动增长 这几天搞Oracle,想让表的主键实现自动增长,查网络实现如下: create table simon_example ( id number(4) not null pr ...

  6. Linux 硬连接和软连接的原理 (in使用)

    引子 目前,UNIX的文件系统有很多种实现,例如UFS(基于BSD的UNIX文件系统).ext3.ext4.ZFS和Reiserfs等等. 不论哪一种文件系统,总是需要存储数据.硬盘的最小存储单位是扇 ...

  7. Linux企业级项目实践之网络爬虫(4)——主程序流程

    当我们设计好程序框架之后就要开始实现它了.第一步当然是要实现主程序的流程框架.之后我们逐渐填充每个流程的细节和其需要调用的模块. 主程序的流程如下: 1.  解析命令行参数,并根据参数跳转到相应的处理 ...

  8. Android 状态栏通知Notification、NotificationManager简介

    Notification(通知)一般用在电话,短信,邮件,闹钟铃声,在手机的状态栏上就会出现一个小图标,提示用户处理这个通知,这时手从上方滑动状态栏就可以展开并处理这个通知: 在Android系统中, ...

  9. NOI2011 NOI嘉年华

    http://www.lydsy.com/JudgeOnline/problem.php?id=2436 首先离散化,离散化后时间范围为[1,cnt]. 求出H[i][j],表示时间范围在[i,j]的 ...

  10. 以Crypto++实现RSA加解密二进制数据

    网上一大片讲怎么加解密字符串的,找了大半天也没找到讲加解密二进制数据的,于是自己研究了下,分享给大家. 加解密函数: #include <rsa.h> #include <randp ...