zoukankan      html  css  js  c++  java
  • 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的人自己管理内存。

  • 相关阅读:
    『Python』装饰器
    『Yaml』配置文件读写包
    『Python CoolBook』数据结构和算法_字典比较&字典和集合
    『TensorFlow』滑动平均
    在ASP.NET 5中如何方便的添加前端库
    使用VS把ASP.NET 5的应用发布到Linux的Docker上
    CQRS及.NET中的参考资料
    ASP.NET Identity 3.0教程
    对ASP.NET 5和ASP.NET MVC 6应用程序进行集成测试
    Bootstrap看厌了?试试Metro UI CSS吧
  • 原文地址:https://www.cnblogs.com/nn0p/p/4167607.html
Copyright © 2011-2022 走看看