因为要学习google开源的cartographer,其中涉及到谷歌的一个数据读取和存储的部件(类似于xml,性能远超xml)。
在ubuntu下,因为先按照cartographer的教程来,所以一不小心已经安装了protocol。点击打开链接
关键语句
sudo apt-get install libprotobuf-dev protobuf-compiler
下面进入google protocol的摸索过程
首先你要 翻 * 墙
这个是他们主页 点击打开链接
protocol是一个完全抽象的数据存储和读取的包,独立于操作系统,独立于语言。所以不论是linux还是win,不论是c++ python c# java R GO 都可以使用。
其储存形式是二进制文件,所以相比于xml,对于相同的数据,能节约3-10倍空间,存储和读取效率高20-100倍。
举个例子:
数据源
xml
<person>
<name>John Doe</name>
<email>jdoe@example.com</email>
</person>
protocol
# Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {
name: "John Doe"
email: "jdoe@example.com"
}
输出
xml
cout << "Name: "
<< person.getElementsByTagName("name")->item(0)->innerText()
<< endl;
cout << "E-mail: "
<< person.getElementsByTagName("email")->item(0)->innerText()
<< endl;
protocol
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
哪个更人性化一目了然。
下面是对tutorial的一些搬运:
最重要的三点:
- Define message formats in a
.proto
file. - Use the protocol buffer compiler.
- Use the C++ protocol buffer API to write and read messages.
文件是.proto形式,就像上面看到的那样
.proto形式的文件还不能直接使用,因为这个是抽象的,独立于平台和语言,所以有一个编译器,自动把.proto文件翻译成平台下你要的语言,我这里是cpp。
直接调用编译器生成的.cc和.h文件,压根不用关心内怎么实现的,反正编译器帮你做好了,你要做的就是调用API。
首先在空文件夹中新建一个addressbook.proto
内容如下
package tutorial;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
原始数据类型可以是
bool
,
int32
,
float
,
double
, and
string
其他数据类型也可以一级一级包含,在代码中已经很明确了。
package tutorial;
意思是命名空间namespace
required声明的变量是必须被初始化的,如果没有初始化,在debug模式下会报错。
optional声明的变量是可以选择性初始化。
repeated声明的变量是可以重复添加的。
注意一些=1 =2 =3,是一种寻址机制,1-15在生成的bin中,可以快速的被读取和写入,所以重复使用的数据尽量放在1-15号。
下面就是编译了,注意这儿的编译只是将.proto文件翻译成我们要的文件,并不是生成什么可执行程序。
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
我比较偷懒就直接在命令行中这样写
protoc -I=./ --cpp_out=./ ./addressbook.proto
之后会生成两个文件分别是
addressbook.pb.h addressbook.pb.cc
这儿贴一下生成的东西
addressbook.pb.h
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: addressbook.proto
#ifndef PROTOBUF_addressbook_2eproto__INCLUDED
#define PROTOBUF_addressbook_2eproto__INCLUDED
#include <string>
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 2006000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 2006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_enum_reflection.h>
#include <google/protobuf/unknown_field_set.h>
// @@protoc_insertion_point(includes)
namespace tutorial {
// Internal implementation detail -- do not call these.
void protobuf_AddDesc_addressbook_2eproto();
void protobuf_AssignDesc_addressbook_2eproto();
void protobuf_ShutdownFile_addressbook_2eproto();
class Person;
class Person_PhoneNumber;
class AddressBook;
enum Person_PhoneType {
Person_PhoneType_MOBILE = 0,
Person_PhoneType_HOME = 1,
Person_PhoneType_WORK = 2
};
bool Person_PhoneType_IsValid(int value);
const Person_PhoneType Person_PhoneType_PhoneType_MIN = Person_PhoneType_MOBILE;
const Person_PhoneType Person_PhoneType_PhoneType_MAX = Person_PhoneType_WORK;
const int Person_PhoneType_PhoneType_ARRAYSIZE = Person_PhoneType_PhoneType_MAX + 1;
const ::google::protobuf::EnumDescriptor* Person_PhoneType_descriptor();
inline const ::std::string& Person_PhoneType_Name(Person_PhoneType value) {
return ::google::protobuf::internal::NameOfEnum(
Person_PhoneType_descriptor(), value);
}
inline bool Person_PhoneType_Parse(
const ::std::string& name, Person_PhoneType* value) {
return ::google::protobuf::internal::ParseNamedEnum<Person_PhoneType>(
Person_PhoneType_descriptor(), name, value);
}
// ===================================================================
class Person_PhoneNumber : public ::google::protobuf::Message {
public:
Person_PhoneNumber();
virtual ~Person_PhoneNumber();
Person_PhoneNumber(const Person_PhoneNumber& from);
inline Person_PhoneNumber& operator=(const Person_PhoneNumber& from) {
CopyFrom(from);
return *this;
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
static const Person_PhoneNumber& default_instance();
void Swap(Person_PhoneNumber* other);
// implements Message ----------------------------------------------
Person_PhoneNumber* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const Person_PhoneNumber& from);
void MergeFrom(const Person_PhoneNumber& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// required string number = 1;
inline bool has_number() const;
inline void clear_number();
static const int kNumberFieldNumber = 1;
inline const ::std::string& number() const;
inline void set_number(const ::std::string& value);
inline void set_number(const char* value);
inline void set_number(const char* value, size_t size);
inline ::std::string* mutable_number();
inline ::std::string* release_number();
inline void set_allocated_number(::std::string* number);
// optional .tutorial.Person.PhoneType type = 2 [default = HOME];
inline bool has_type() const;
inline void clear_type();
static const int kTypeFieldNumber = 2;
inline ::tutorial::Person_PhoneType type() const;
inline void set_type(::tutorial::Person_PhoneType value);
// @@protoc_insertion_point(class_scope:tutorial.Person.PhoneNumber)
private:
inline void set_has_number();
inline void clear_has_number();
inline void set_has_type();
inline void clear_has_type();
::google::protobuf::UnknownFieldSet _unknown_fields_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::std::string* number_;
int type_;
friend void protobuf_AddDesc_addressbook_2eproto();
friend void protobuf_AssignDesc_addressbook_2eproto();
friend void protobuf_ShutdownFile_addressbook_2eproto();
void InitAsDefaultInstance();
static Person_PhoneNumber* default_instance_;
};
// -------------------------------------------------------------------
class Person : public ::google::protobuf::Message {
public:
Person();
virtual ~Person();
Person(const Person& from);
inline Person& operator=(const Person& from) {
CopyFrom(from);
return *this;
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
static const Person& default_instance();
void Swap(Person* other);
// implements Message ----------------------------------------------
Person* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const Person& from);
void MergeFrom(const Person& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
typedef Person_PhoneNumber PhoneNumber;
typedef Person_PhoneType PhoneType;
static const PhoneType MOBILE = Person_PhoneType_MOBILE;
static const PhoneType HOME = Person_PhoneType_HOME;
static const PhoneType WORK = Person_PhoneType_WORK;
static inline bool PhoneType_IsValid(int value) {
return Person_PhoneType_IsValid(value);
}
static const PhoneType PhoneType_MIN =
Person_PhoneType_PhoneType_MIN;
static const PhoneType PhoneType_MAX =
Person_PhoneType_PhoneType_MAX;
static const int PhoneType_ARRAYSIZE =
Person_PhoneType_PhoneType_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
PhoneType_descriptor() {
return Person_PhoneType_descriptor();
}
static inline const ::std::string& PhoneType_Name(PhoneType value) {
return Person_PhoneType_Name(value);
}
static inline bool PhoneType_Parse(const ::std::string& name,
PhoneType* value) {
return Person_PhoneType_Parse(name, value);
}
// accessors -------------------------------------------------------
// required string name = 1;
inline bool has_name() const;
inline void clear_name();
static const int kNameFieldNumber = 1;
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
// required int32 id = 2;
inline bool has_id() const;
inline void clear_id();
static const int kIdFieldNumber = 2;
inline ::google::protobuf::int32 id() const;
inline void set_id(::google::protobuf::int32 value);
// optional string email = 3;
inline bool has_email() const;
inline void clear_email();
static const int kEmailFieldNumber = 3;
inline const ::std::string& email() const;
inline void set_email(const ::std::string& value);
inline void set_email(const char* value);
inline void set_email(const char* value, size_t size);
inline ::std::string* mutable_email();
inline ::std::string* release_email();
inline void set_allocated_email(::std::string* email);
// repeated .tutorial.Person.PhoneNumber phone = 4;
inline int phone_size() const;
inline void clear_phone();
static const int kPhoneFieldNumber = 4;
inline const ::tutorial::Person_PhoneNumber& phone(int index) const;
inline ::tutorial::Person_PhoneNumber* mutable_phone(int index);
inline ::tutorial::Person_PhoneNumber* add_phone();
inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >&
phone() const;
inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >*
mutable_phone();
// @@protoc_insertion_point(class_scope:tutorial.Person)
private:
inline void set_has_name();
inline void clear_has_name();
inline void set_has_id();
inline void clear_has_id();
inline void set_has_email();
inline void clear_has_email();
::google::protobuf::UnknownFieldSet _unknown_fields_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::std::string* name_;
::std::string* email_;
::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber > phone_;
::google::protobuf::int32 id_;
friend void protobuf_AddDesc_addressbook_2eproto();
friend void protobuf_AssignDesc_addressbook_2eproto();
friend void protobuf_ShutdownFile_addressbook_2eproto();
void InitAsDefaultInstance();
static Person* default_instance_;
};
// -------------------------------------------------------------------
class AddressBook : public ::google::protobuf::Message {
public:
AddressBook();
virtual ~AddressBo