google protobuf使用

2023-11-04

http://www.cnblogs.com/youxin/p/4073703.html


If you get the source from github, you need to generate the configure script first:

$ ./autogen.sh

This will download gtest source (which is used for C++ Protocol Buffer unit-tests) to the current directory and run automake, autoconf, etc. to generate the configure script and various template makefiles.

运行这个会下载gtest(google单元测试框架)。由于google访问不了,这个这个没有成功。

 

直接在csdnhttp://download.csdn.net/download/canlets/6878023 下载的protobuf2.5.0.

tar zxvf protobuf-2.4.1.tar.gz
cd protobuf-2.4.1
./configure
make
make check
make install
安装结束。
验证:
查看是否安装成功:protoc --version
如果出现:libprotoc 2.4.1 则说明安装成功!
如果出现错误:

 

tar zxvf protobuf-2.5.0.tar.gz
 
./configure
make
make check
make install
安装结束。
验证:
查看是否安装成功:protoc --version
如果出现:libprotoc 2.5.0 则说明安装成功!
如果出现错误:
protoc: error while loading shared libraries: libprotobuf.so.0: cannot open
shared object file: No such file or directory
The issue is that Ubuntu 8.04 doesn't include /usr/local/lib in
library paths.
To fix it for your current terminal session, just type in
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

 

 安装完成后在终端下执行

  vim ~/.profile (我加在了/etc/profile里)

  打开配置文件,在该文件中添加

  export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

  然后保存退出,接下来执行

  source ~/.profile

  是配置文件修改生效,最后执行

  protoc --version

  查看protobuf版本以测试是否安装成功

 

 

root@iZ23onhpqvwZ:~/ms/protobuf/protobuf-2.5.0# protoc --version
libprotoc 2.5.0

转:protobuf c++入门

1、在.proto文件中定义消息格式

2、使用protobuf编译器
3、使用c++ api来读写消息
 
windows  protobuf编译
我下载的是2.6.1的版本
打开vsprojects目录,里面有一个.sln文件,打开
vsprojects里面有一个readme.txt,告诉了如何安装:
This directory contains project files for compiling Protocol Buffers using
MSVC.  This is not the recommended way to do Protocol Buffer development --
we prefer to develop under a Unix-like environment -- but it may be more
accessible to those who primarily work with MSVC.

Compiling and Installing
========================

1) Open protobuf.sln in Microsoft Visual Studio.
2) Choose "Debug" or "Release" configuration as desired.*
3) From the Build menu, choose "Build Solution".  Wait for compiling to finish.
4) From a command shell, run tests.exe and lite-test.exe and check that all
   tests pass.
5) Run extract_includes.bat to copy all the public headers into a separate
   "include" directory (under the top-level package directory).
6) Copy the contents of the include directory to wherever you want to put
   headers.
7) Copy protoc.exe wherever you put build tools (probably somewhere in your
   PATH).
8) Copy libprotobuf.lib, libprotobuf-lite.lib, and libprotoc.lib wherever you
   put libraries.

* To avoid conflicts between the MSVC debug and release runtime libraries, when
  compiling a debug build of your application, you may need to link against a
  debug build of libprotobuf.lib.  Similarly, release builds should link against
  release libs.

DLLs vs. static linking
=======================

Static linking is now the default for the Protocol Buffer libraries.  Due to
issues with Win32's use of a separate heap for each DLL, as well as binary
compatibility issues between different versions of MSVC's STL library, it is
recommended that you use static linkage only.  However, it is possible to
build libprotobuf and libprotoc as DLLs if you really want.  To do this,
do the following:

  1) Open protobuf.sln in MSVC.
  2) For each of the projects libprotobuf, libprotobuf-lite, and libprotoc, do
     the following:
    2a) Right-click the project and choose "properties".
    2b) From the side bar, choose "General", under "Configuration Properties".
    2c) Change the "Configuration Type" to "Dynamic Library (.dll)".
    2d) From the side bar, choose "Preprocessor", under "C/C++".
    2e) Add PROTOBUF_USE_DLLS to the list of preprocessor defines.
  3) When compiling your project, make sure to #define PROTOBUF_USE_DLLS.

When distributing your software to end users, we strongly recommend that you
do NOT install libprotobuf.dll or libprotoc.dll to any shared location.
Instead, keep these libraries next to your binaries, in your application's
own install directory.  C++ makes it very difficult to maintain binary
compatibility between releases, so it is likely that future versions of these
libraries will *not* be usable as drop-in replacements.

If your project is itself a DLL intended for use by third-party software, we
recommend that you do NOT expose protocol buffer objects in your library's
public interface, and that you statically link protocol buffers into your
library.

ZLib support
============

If you want to include GzipInputStream and GzipOutputStream
(google/protobuf/io/gzip_stream.h) in libprotoc, you will need to do a few
additional steps:

1) Obtain a copy of the zlib library.  The pre-compiled DLL at zlib.net works.
2) Make sure zlib's two headers are in your include path and that the .lib file
   is in your library path.  You could place all three files directly into the
   vsproject directory to compile libprotobuf, but they need to be visible to
   your own project as well, so you should probably just put them into the
   VC shared icnlude and library directories.
3) Right-click on the "tests" project and choose "properties".  Navigate the
   sidebar to "Configuration Properties" -> "Linker" -> "Input".
4) Under "Additional Dependencies", add the name of the zlib .lib file (e.g.
   zdll.lib).  Make sure to update both the Debug and Release configurations.
5) If you are compiling libprotobuf and libprotoc as DLLs (see previous
   section), repeat steps 2 and 3 for the libprotobuf and libprotoc projects.
   If you are compiling them as static libraries, then you will need to link
   against the zlib library directly from your own app.
6) Edit config.h (in the vsprojects directory) and un-comment the line that
   #defines HAVE_ZLIB.  (Or, alternatively, define this macro via the project
   settings.)

Notes on Compiler Warnings
==========================

The following warnings have been disabled while building the protobuf libraries
and compiler.  You may have to disable some of them in your own project as
well, or live with them.

C4018 - 'expression' : signed/unsigned mismatch
C4146 - unary minus operator applied to unsigned type, result still unsigned
C4244 - Conversion from 'type1' to 'type2', possible loss of data.
C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by
        clients of class 'type2'
C4267 - Conversion from 'size_t' to 'type', possible loss of data.
C4305 - 'identifier' : truncation from 'type1' to 'type2'
C4355 - 'this' : used in base member initializer list
C4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning)
C4996 - 'function': was declared deprecated

C4251 is of particular note, if you are compiling the Protocol Buffer library
as a DLL (see previous section).  The protocol buffer library uses templates in
its public interfaces.  MSVC does not provide any reasonable way to export
template classes from a DLL.  However, in practice, it appears that exporting
templates is not necessary anyway.  Since the complete definition of any
template is available in the header files, anyone importing the DLL will just
end up compiling instances of the templates into their own binary.  The
Protocol Buffer implementation does not rely on static template members being
unique, so there should be no problem with this, but MSVC prints warning
nevertheless.  So, we disable it.  Unfortunately, this warning will also be
produced when compiling code which merely uses protocol buffers, meaning you
may have to disable it in your code too.

按照上面的很难成功,搞了n次,终与生成了,参考下面的。

http://blog.csdn.net/kandyer/article/details/10042715

0、为何使用protobuf?
 
1、原始内存数据结构,可以以二进制方式sent/saved.这种方式需要相同的内存布局和字节序。
2、以ad-hoc方式将数据项编码成一个简单字符串----比如,将4个int类型编码成"12:3:-23:67"。这种方式简灵活。适用于简单数据。
3、将数据序列化为XML。这种方式很流行,因为xml可读性好,编码解码方便,性能也好。仅仅XML dom树比较复杂。
 
protobuf可以很好的解决上述问题。你编写 一个.proto文件来描述数据结构。protobuf编译器使用它创建一个类,使用二进制方式自动编码/解码该数据结构。生成的类提供getter/setter方法
 
最重要的是,protobuf支持在此基础上进行格式扩展。
关于数据类型:

要通信,必须有协议,否则双方无法理解对方的码流。在protobuf中,协议是由一系列的消息组成的。因此最重要的就是定义通信时使用到的消息格式。

 

Protobuf消息定义

消息由至少一个字段组合而成,类似于C语言中的结构。每个字段都有一定的格式。

字段格式:限定修饰符① | 数据类型② | 字段名称③ | = | 字段编码值④ | [字段默认值⑤]

①.限定修饰符包含 required\optional\repeated

 

Required: 表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。

Optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。---因为optional字段的特性,很多接口在升级版本中都把后来添加的字段都统一的设置为optional字段,这样老的版本无需升级程序也可以正常的与新的软件进行通信,只不过新的字段无法识别而已,因为并不是每个节点都需要新的功能,因此可以做到按需升级和平滑过渡。

Repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。

 

②.数据类型

 

Protobuf定义了一套基本数据类型。几乎都可以映射到C++\Java等语言的基础数据类型.

      

protobuf 数据类型

描述

打包

C++语言映射

bool

布尔类型

1字节

bool

double

64位浮点数

N

double

float

32为浮点数

N

float

int32

32位整数、

N

int

uin32

无符号32位整数

N

unsigned int

int64

64位整数

N

__int64

uint64

64为无符号整

N

unsigned __int64

sint32

32位整数,处理负数效率更高

N

int32

sing64

64位整数 处理负数效率更高

N

__int64

fixed32

32位无符号整数

4

unsigned int32

fixed64

64位无符号整数

8

unsigned __int64

sfixed32

32位整数、能以更高的效率处理负数

4

unsigned int32

sfixed64

64为整数

8

unsigned __int64

string

只能处理 ASCII字符

N

std::string

bytes

用于处理多字节的语言字符、如中文

N

std::string

enum

可以包含一个用户自定义的枚举类型uint32

N(uint32)

enum

message

可以包含一个用户自定义的消息类型

N

object of class

N 表示打包的字节并不是固定。而是根据数据的大小或者长度。

例如int32,如果数值比较小,在0~127时,使用一个字节打包。

关于枚举的打包方式和uint32相同。

关于message,类似于C语言中的结构包含另外一个结构作为数据成员一样。

关于 fixed32 和int32的区别。fixed32的打包效率比int32的效率高,但是使用的空间一般比int32多。因此一个属于时间效率高,一个属于空间效率高。根据项目的实际情况,一般选择fixed32,如果遇到对传输数据量要求比较苛刻的环境,可以选择int32.

③.字段名称

 

字段名称的命名与C、C++、Java等语言的变量命名方式几乎是相同的。

protobuf建议字段的命名采用以下划线分割的驼峰式。例如 first_name 而不是firstName.

④.字段编码值

有了该值,通信双方才能互相识别对方的字段。当然相同的编码值,其限定修饰符和数据类型必须相同。

编码值的取值范围为 1~2^32(4294967296)。

其中 1~15的编码时间和空间效率都是最高的,编码值越大,其编码的时间和空间效率就越低(相对于1-15),当然一般情况下相邻的2个值编码效率的是相同的,除非2个值恰好实在4字节,12字节,20字节等的临界区。比如15和16.

1900~2000编码值为Google protobuf 系统内部保留值,建议不要在自己的项目中使用。

protobuf 还建议把经常要传递的值把其字段编码设置为1-15之间的值。

消息中的字段的编码值无需连续,只要是合法的,并且不能在同一个消息中有字段包含相同的编码值。

建议:项目投入运营以后涉及到版本升级时的新增消息字段全部使用optional或者repeated,尽量不实用required。如果使用了required,需要全网统一升级,如果使用optional或者repeated可以平滑升级。

 

⑤.默认值。当在传递数据时,对于required数据类型,如果用户没有设置值,则使用默认值传递到对端。当接受数据是,对于optional字段,如果没有接收到optional字段,则设置为默认值。

 

关于import

protobuf 接口文件可以像C语言的h文件一个,分离为多个,在需要的时候通过 import导入需要对文件。其行为和C语言的#include或者java的import的行为大致相同。

关于package

避免名称冲突,可以给每个文件指定一个package名称,对于java解析为java中的包。对于C++则解析为名称空间。

 

关于message

支持嵌套消息,消息可以包含另一个消息作为其字段。也可以在消息内定义一个新的消息。

关于enum

枚举的定义和C++相同,但是有一些限制。

枚举值必须大于等于0的整数。

使用分号(;)分隔枚举变量而不是C++语言中的逗号(,)

eg.

enum VoipProtocol 

{

    H323 = 1;

    SIP  = 2;

    MGCP = 3;

    H248 = 4;

}

 

 

 
 
1、定义协议格式
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; 
}
该结构与c++或java很像.
 
.proto文件以包声明开始,防止名字冲突。
简单类型:bool, int32, float, double, string.
其它类型:如上述的Person, PhoneNumber
 
类型可以嵌套。
“=1”, “=2”标识唯一“tag”.tag数1-15需要至少一个字节。
 
required: 必须设置它的值
optional: 可以设置,也可以不设置它的值
repeated: 可以认为是动态分配的数组
google工程师认为使用required威害更大, 他们更喜欢使用optional, repeated.
  
其中字段标签标示了字段在二进制流中存放的位置,这个是必须的,而且序列化与反序列化的时候相同的字段的Tag值必须对应,否则反序列化会出现意想不到的问题。

2、编译你的协议
 
运行protoc 来生成c++文件:
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
  1. protoc proto文件路径 --cpp_out=C++代码文件导出目录  在使用中我发现有一点需要注意,就是--cpp_out的目录是根据proto文件的路径为基础的,也就是说:假设proto文件位于src目录下,希望将C++代码也导出到src目录下,那么--cpp_out直接=.就可以了。不需要再写一遍src/,如果写了src/,那么代码导出的目录将是src/src/(即使src/src不存在,也会被创建)
生成的文件为:
protoc --cpp_out=.    ./addressbook.proto 
 
addressbook.pb.h, 
addressbook.pb.cc
 
3、protobuf API
 整个头文件:
// 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 ~AddressBook();

  AddressBook(const AddressBook& from);

  inline AddressBook& operator=(const AddressBook& 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 AddressBook& default_instance();

  void Swap(AddressBook* other);

  // implements Message ----------------------------------------------

  AddressBook* New() const;
  void CopyFrom(const ::google::protobuf::Message& from);
  void MergeFrom(const ::google::protobuf::Message& from);
  void CopyFrom(const AddressBook& from);
  void MergeFrom(const AddressBook& 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 -------------------------------------------------------

  // repeated .tutorial.Person person = 1;
  inline int person_size() const;
  inline void clear_person();
  static const int kPersonFieldNumber = 1;
  inline const ::tutorial::Person& person(int index) const;
  inline ::tutorial::Person* mutable_person(int index);
  inline ::tutorial::Person* add_person();
  inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person >&
      person() const;
  inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person >*
      mutable_person();

  // @@protoc_insertion_point(class_scope:tutorial.AddressBook)
 private:

  ::google::protobuf::UnknownFieldSet _unknown_fields_;

  ::google::protobuf::uint32 _has_bits_[1];
  mutable int _cached_size_;
  ::google::protobuf::RepeatedPtrField< ::tutorial::Person > person_;
  friend void  protobuf_AddDesc_addressbook_2eproto();
  friend void protobuf_AssignDesc_addressbook_2eproto();
  friend void protobuf_ShutdownFile_addressbook_2eproto();

  void InitAsDefaultInstance();
  static AddressBook* default_instance_;
};
// ===================================================================


// ===================================================================

// Person_PhoneNumber

// required string number = 1;
inline bool Person_PhoneNumber::has_number() const {
  return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void Person_PhoneNumber::set_has_number() {
  _has_bits_[0] |= 0x00000001u;
}
inline void Person_PhoneNumber::clear_has_number() {
  _has_bits_[0] &= ~0x00000001u;
}
inline void Person_PhoneNumber::clear_number() {
  if (number_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    number_->clear();
  }
  clear_has_number();
}
inline const ::std::string& Person_PhoneNumber::number() const {
  // @@protoc_insertion_point(field_get:tutorial.Person.PhoneNumber.number)
  return *number_;
}
inline void Person_PhoneNumber::set_number(const ::std::string& value) {
  set_has_number();
  if (number_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    number_ = new ::std::string;
  }
  number_->assign(value);
  // @@protoc_insertion_point(field_set:tutorial.Person.PhoneNumber.number)
}
inline void Person_PhoneNumber::set_number(const char* value) {
  set_has_number();
  if (number_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    number_ = new ::std::string;
  }
  number_->assign(value);
  // @@protoc_insertion_point(field_set_char:tutorial.Person.PhoneNumber.number)
}
inline void Person_PhoneNumber::set_number(const char* value, size_t size) {
  set_has_number();
  if (number_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    number_ = new ::std::string;
  }
  number_->assign(reinterpret_cast<const char*>(value), size);
  // @@protoc_insertion_point(field_set_pointer:tutorial.Person.PhoneNumber.number)
}
inline ::std::string* Person_PhoneNumber::mutable_number() {
  set_has_number();
  if (number_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    number_ = new ::std::string;
  }
  // @@protoc_insertion_point(field_mutable:tutorial.Person.PhoneNumber.number)
  return number_;
}
inline ::std::string* Person_PhoneNumber::release_number() {
  clear_has_number();
  if (number_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    return NULL;
  } else {
    ::std::string* temp = number_;
    number_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
    return temp;
  }
}
inline void Person_PhoneNumber::set_allocated_number(::std::string* number) {
  if (number_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    delete number_;
  }
  if (number) {
    set_has_number();
    number_ = number;
  } else {
    clear_has_number();
    number_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  }
  // @@protoc_insertion_point(field_set_allocated:tutorial.Person.PhoneNumber.number)
}

// optional .tutorial.Person.PhoneType type = 2 [default = HOME];
inline bool Person_PhoneNumber::has_type() const {
  return (_has_bits_[0] & 0x00000002u) != 0;
}
inline void Person_PhoneNumber::set_has_type() {
  _has_bits_[0] |= 0x00000002u;
}
inline void Person_PhoneNumber::clear_has_type() {
  _has_bits_[0] &= ~0x00000002u;
}
inline void Person_PhoneNumber::clear_type() {
  type_ = 1;
  clear_has_type();
}
inline ::tutorial::Person_PhoneType Person_PhoneNumber::type() const {
  // @@protoc_insertion_point(field_get:tutorial.Person.PhoneNumber.type)
  return static_cast< ::tutorial::Person_PhoneType >(type_);
}
inline void Person_PhoneNumber::set_type(::tutorial::Person_PhoneType value) {
  assert(::tutorial::Person_PhoneType_IsValid(value));
  set_has_type();
  type_ = value;
  // @@protoc_insertion_point(field_set:tutorial.Person.PhoneNumber.type)
}

// -------------------------------------------------------------------

// Person

// required string name = 1;
inline bool Person::has_name() const {
  return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void Person::set_has_name() {
  _has_bits_[0] |= 0x00000001u;
}
inline void Person::clear_has_name() {
  _has_bits_[0] &= ~0x00000001u;
}
inline void Person::clear_name() {
  if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    name_->clear();
  }
  clear_has_name();
}
inline const ::std::string& Person::name() const {
  // @@protoc_insertion_point(field_get:tutorial.Person.name)
  return *name_;
}
inline void Person::set_name(const ::std::string& value) {
  set_has_name();
  if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    name_ = new ::std::string;
  }
  name_->assign(value);
  // @@protoc_insertion_point(field_set:tutorial.Person.name)
}
inline void Person::set_name(const char* value) {
  set_has_name();
  if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    name_ = new ::std::string;
  }
  name_->assign(value);
  // @@protoc_insertion_point(field_set_char:tutorial.Person.name)
}
inline void Person::set_name(const char* value, size_t size) {
  set_has_name();
  if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    name_ = new ::std::string;
  }
  name_->assign(reinterpret_cast<const char*>(value), size);
  // @@protoc_insertion_point(field_set_pointer:tutorial.Person.name)
}
inline ::std::string* Person::mutable_name() {
  set_has_name();
  if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    name_ = new ::std::string;
  }
  // @@protoc_insertion_point(field_mutable:tutorial.Person.name)
  return name_;
}
inline ::std::string* Person::release_name() {
  clear_has_name();
  if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    return NULL;
  } else {
    ::std::string* temp = name_;
    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
    return temp;
  }
}
inline void Person::set_allocated_name(::std::string* name) {
  if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    delete name_;
  }
  if (name) {
    set_has_name();
    name_ = name;
  } else {
    clear_has_name();
    name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  }
  // @@protoc_insertion_point(field_set_allocated:tutorial.Person.name)
}

// required int32 id = 2;
inline bool Person::has_id() const {
  return (_has_bits_[0] & 0x00000002u) != 0;
}
inline void Person::set_has_id() {
  _has_bits_[0] |= 0x00000002u;
}
inline void Person::clear_has_id() {
  _has_bits_[0] &= ~0x00000002u;
}
inline void Person::clear_id() {
  id_ = 0;
  clear_has_id();
}
inline ::google::protobuf::int32 Person::id() const {
  // @@protoc_insertion_point(field_get:tutorial.Person.id)
  return id_;
}
inline void Person::set_id(::google::protobuf::int32 value) {
  set_has_id();
  id_ = value;
  // @@protoc_insertion_point(field_set:tutorial.Person.id)
}

// optional string email = 3;
inline bool Person::has_email() const {
  return (_has_bits_[0] & 0x00000004u) != 0;
}
inline void Person::set_has_email() {
  _has_bits_[0] |= 0x00000004u;
}
inline void Person::clear_has_email() {
  _has_bits_[0] &= ~0x00000004u;
}
inline void Person::clear_email() {
  if (email_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    email_->clear();
  }
  clear_has_email();
}
inline const ::std::string& Person::email() const {
  // @@protoc_insertion_point(field_get:tutorial.Person.email)
  return *email_;
}
inline void Person::set_email(const ::std::string& value) {
  set_has_email();
  if (email_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    email_ = new ::std::string;
  }
  email_->assign(value);
  // @@protoc_insertion_point(field_set:tutorial.Person.email)
}
inline void Person::set_email(const char* value) {
  set_has_email();
  if (email_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    email_ = new ::std::string;
  }
  email_->assign(value);
  // @@protoc_insertion_point(field_set_char:tutorial.Person.email)
}
inline void Person::set_email(const char* value, size_t size) {
  set_has_email();
  if (email_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    email_ = new ::std::string;
  }
  email_->assign(reinterpret_cast<const char*>(value), size);
  // @@protoc_insertion_point(field_set_pointer:tutorial.Person.email)
}
inline ::std::string* Person::mutable_email() {
  set_has_email();
  if (email_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    email_ = new ::std::string;
  }
  // @@protoc_insertion_point(field_mutable:tutorial.Person.email)
  return email_;
}
inline ::std::string* Person::release_email() {
  clear_has_email();
  if (email_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    return NULL;
  } else {
    ::std::string* temp = email_;
    email_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
    return temp;
  }
}
inline void Person::set_allocated_email(::std::string* email) {
  if (email_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
    delete email_;
  }
  if (email) {
    set_has_email();
    email_ = email;
  } else {
    clear_has_email();
    email_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  }
  // @@protoc_insertion_point(field_set_allocated:tutorial.Person.email)
}

// repeated .tutorial.Person.PhoneNumber phone = 4;
inline int Person::phone_size() const {
  return phone_.size();
}
inline void Person::clear_phone() {
  phone_.Clear();
}
inline const ::tutorial::Person_PhoneNumber& Person::phone(int index) const {
  // @@protoc_insertion_point(field_get:tutorial.Person.phone)
  return phone_.Get(index);
}
inline ::tutorial::Person_PhoneNumber* Person::mutable_phone(int index) {
  // @@protoc_insertion_point(field_mutable:tutorial.Person.phone)
  return phone_.Mutable(index);
}
inline ::tutorial::Person_PhoneNumber* Person::add_phone() {
  // @@protoc_insertion_point(field_add:tutorial.Person.phone)
  return phone_.Add();
}
inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >&
Person::phone() const {
  // @@protoc_insertion_point(field_list:tutorial.Person.phone)
  return phone_;
}
inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >*
Person::mutable_phone() {
  // @@protoc_insertion_point(field_mutable_list:tutorial.Person.phone)
  return &phone_;
}

// -------------------------------------------------------------------

// AddressBook

// repeated .tutorial.Person person = 1;
inline int AddressBook::person_size() const {
  return person_.size();
}
inline void AddressBook::clear_person() {
  person_.Clear();
}
inline const ::tutorial::Person& AddressBook::person(int index) const {
  // @@protoc_insertion_point(field_get:tutorial.AddressBook.person)
  return person_.Get(index);
}
inline ::tutorial::Person* AddressBook::mutable_person(int index) {
  // @@protoc_insertion_point(field_mutable:tutorial.AddressBook.person)
  return person_.Mutable(index);
}
inline ::tutorial::Person* AddressBook::add_person() {
  // @@protoc_insertion_point(field_add:tutorial.AddressBook.person)
  return person_.Add();
}
inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person >&
AddressBook::person() const {
  // @@protoc_insertion_point(field_list:tutorial.AddressBook.person)
  return person_;
}
inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person >*
AddressBook::mutable_person() {
  // @@protoc_insertion_point(field_mutable_list:tutorial.AddressBook.person)
  return &person_;
}


// @@protoc_insertion_point(namespace_scope)

}  // namespace tutorial

#ifndef SWIG
namespace google {
namespace protobuf {

template <> struct is_proto_enum< ::tutorial::Person_PhoneType> : ::google::protobuf::internal::true_type {};
template <>
inline const EnumDescriptor* GetEnumDescriptor< ::tutorial::Person_PhoneType>() {
  return ::tutorial::Person_PhoneType_descriptor();
}

}  // namespace google
}  // namespace protobuf
#endif  // SWIG

// @@protoc_insertion_point(global_scope)

#endif  // PROTOBUF_addressbook_2eproto__INCLUDED

 

生成的文件中有如下方法: 
// name
  inline bool has_name() const;
  inline void clear_name();
  inline const ::std::string& name() const;
  inline void set_name(const ::std::string& value);
  inline void set_name(const char* value);
  inline ::std::string* mutable_name();

  // id
  inline bool has_id() const;
  inline void clear_id();
  inline int32_t id() const;
  inline void set_id(int32_t value);

  // email
  inline bool has_email() const;
  inline void clear_email();
  inline const ::std::string& email() const;
  inline void set_email(const ::std::string& value);
  inline void set_email(const char* value);
  inline ::std::string* mutable_email();

  // phone
  inline int phone_size() const;
  inline void clear_phone();
  inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >& phone() const;
  inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >* mutable_phone();
  inline const ::tutorial::Person_PhoneNumber& phone(int index) const;
  inline ::tutorial::Person_PhoneNumber* mutable_phone(int index);
  inline ::tutorial::Person_PhoneNumber* add_phone();

4、枚举与嵌套类

 
生成的代码包含一个PhoneType枚举。Person::PhoneType, Person:MOBILE, Person::HOME, Person:WORK.
 
编译器生成的嵌套类称为Person::PhoneNumber. 实际生成类为Person_PhoneNumber.
 
5、标准方法
 

bool IsInitialized() const:                确认required字段是否被设置

string DebugString() const:                返回消息的可读表示,用于调试

void CopyFrom(const Person& from):         使用给定消息值copy

void Clear():                              清除所有元素为空状态

6、解析与序列化
 

bool SerializeToString(string* output) const:        序列化消息,将存储字节的以string方式输出。注意字节是二进,而非文本;

bool ParseFromString(const string& data):            解析给定的string     

bool SerializeToOstream(ostream* output) const:      写消息给定的c++  ostream

bool ParseFromIstream(istream* input):               从给定的c++ istream中解析出消息

7、protobuf和 oo设计
不要继承生成类并在此基础上添加相应的行为
 
8、写消息
 
示例:它从一个文件中读取AddressBook,基 于io添加一个新的Person,并将新的AddressBook写回文件。
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
  cout << "Enter person ID number: ";
  int id;
  cin >> id;
  person->set_id(id);
  cin.ignore(256, '\n');

  cout << "Enter name: ";
  getline(cin, *person->mutable_name());

  cout << "Enter email address (blank for none): ";
  string email;
  getline(cin, email);
  if (!email.empty()) {
    person->set_email(email);
  }

  while (true) {
    cout << "Enter a phone number (or leave blank to finish): ";
    string number;
    getline(cin, number);
    if (number.empty()) {
      break;
    }

    tutorial::Person::PhoneNumber* phone_number = person->add_phone();
    phone_number->set_number(number);

    cout << "Is this a mobile, home, or work phone? ";
    string type;
    getline(cin, type);
    if (type == "mobile") {
      phone_number->set_type(tutorial::Person::MOBILE);
    } else if (type == "home") {
      phone_number->set_type(tutorial::Person::HOME);
    } else if (type == "work") {
      phone_number->set_type(tutorial::Person::WORK);
    } else {
      cout << "Unknown phone type.  Using default." << endl;
    }
  }
}

// Main function:  Reads the entire address book from a file,
//   adds one person based on user input, then writes it back out to the same
//   file.
int main(int argc, char* argv[]) {
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (argc != 2) {
    cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
    return -1;
  }

  tutorial::AddressBook address_book;

  {
    // Read the existing address book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!input) {
      cout << argv[1] << ": File not found.  Creating a new file." << endl;
    } else if (!address_book.ParseFromIstream(&input)) {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  // Add an address.
  PromptForAddress(address_book.add_person());

  {
    // Write the new address book back to disk.
    fstream output(argv[1], ios::out | ios::trunc | ios::binary);
    if (!address_book.SerializeToOstream(&output)) {
      cerr << "Failed to write address book." << endl;
      return -1;
    }
  }

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

 g++ addPerson.cpp  addressbook.pb.cc -o addPerson   -lpthread  -l protobuf

生成addPerson.

运行./addPerson addressbook1

 

注意使用GOOGL E_PROTOBUF_VERIFY_VERSION宏。每一个.pb.cc文件在启动时都将自动调用该宏。
 
注意在程序结尾处调用ShutdownProtobufLibrary()。
 
9、读消息 
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;

// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {
  for (int i = 0; i < address_book.person_size(); i++) {
    const tutorial::Person& person = address_book.person(i);

    cout << "Person ID: " << person.id() << endl;
    cout << "  Name: " << person.name() << endl;
    if (person.has_email()) {
      cout << "  E-mail address: " << person.email() << endl;
    }

    for (int j = 0; j < person.phone_size(); j++) {
      const tutorial::Person::PhoneNumber& phone_number = person.phone(j);

      switch (phone_number.type()) {
        case tutorial::Person::MOBILE:
          cout << "  Mobile phone #: ";
          break;
        case tutorial::Person::HOME:
          cout << "  Home phone #: ";
          break;
        case tutorial::Person::WORK:
          cout << "  Work phone #: ";
          break;
      }
      cout << phone_number.number() << endl;
    }
  }
}

// Main function:  Reads the entire address book from a file and prints all
//   the information inside.
int main(int argc, char* argv[]) {
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (argc != 2) {
    cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
    return -1;
  }

  tutorial::AddressBook address_book;

  {
    // Read the existing address book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!address_book.ParseFromIstream(&input)) {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  ListPeople(address_book);

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

g++ readPerson.cpp  addressbook.pb.cc -o readPerson   -lpthread  -l protobuf

运行:

./readPerson addressbook1
Person ID: 1
Name: suming
E-mail address: gz
Mobile phone #: 13631279712
Home phone #: 4578
Work phone #: 963
Work phone #: 65

10、扩展protobuf
 
如果希望向后兼容,必须遵循:
a、不必更改tag数
b、不必添加或删除任何required字段
c、可以删除optional或repeated字段
d、可以添加新的optional或repeated字段,但你必须使用新的tag数。
 
11、优化
c++的protobuf库,已经极大地优化了。合理使用可以改善性能。
a、如果可能,复用message对象。
b、关于多线程的内存分配器
 
12、高级用法
 
protobuf的消息类的一个关键特性是, 反射(reflection)。可以使用xml或json来实现。 参考
 
 
================================================================
常见问题:
1、undefined reference to `pthread_once' 
使用-lpthread:
 
2、error while loading shared libraries: libprotobuf.so.7: cannot open shared object file: No such file or directory
使用-Wl,-Bstatic -lprotobuf -Wl,-Bdynamic -lpthread
 
 

参考:http://blog.csdn.net/zmzsoftware/article/details/17356199

 

一个简单的例子:

helloworld.proto

package hw;
message helloworld
{
    required int32 id=1;//id
    required string str=2;//str
    optional int32  opt=3;//opt

}

protoc -I=. --cpp_out=.   helloworld.proto

写序列化消息的进程

#include"helloworld.pb.h"
#include<iostream>
#include<fstream>
using namespace std;

int main()
{
    hw::helloworld msg1;
    msg1.set_id(101);
    msg1.set_str("hello");
    
    fstream output("./log",ios::out| ios::trunc | ios::binary);
    if(! msg1.SerializeToOstream(&output))
    {
        cerr<<"Failed to write msg!"<<endl;
        return -1;
    }
    
    return 0;
}
编译 write.cc 
 g++  msg.pb.cc write.cc -o write  `pkg-config --cflags --libs protobuf` -lpthread
 
执行write 
./write, 可以看到生成了log文件

root@iZ23onhpqvwZ:~/ms/protobuf/helloworld# xxd log 查看log二进制
0000000: 0865 1205 6865 6c6c 6f .e..hello

 

 
写反序列化的进程
reader.cc
#include"helloworld.pb.h"
#include<iostream>
#include<fstream>
using namespace std;

void ListMsg(const hw::helloworld &msg)
{
    cout<<msg.id()<<endl;
    cout<<msg.str()<<endl;
}

int main(int argc,char **argv)
{
    hw::helloworld msg1;
    msg1.set_id(101);
    msg1.set_str("hello");
    
    fstream input("./log",ios::in | ios::binary);
    if(!msg1.ParseFromIstream(&input))
    {
       cerr<<"failed to parsed address book!";
       return -1;
    }
    
    ListMsg(msg1);
    return 0;
}
编译:g++  msg.pb.cc reader.cc -o reader  `pkg-config --cflags --libs protobuf` -lpthread
执行./reader 输出 :
101
hello
 
makefile文件:
all:write reader

clean:
    rm -f write reader helloworld.*.cc helloworld.*.h *.o log
    
proto_msg:
    protoc -I=. --cpp_out=.  helloworld.proto
    
write:helloworld.pb.cc write.cpp 
    g++ $^ -o  $@ -l protobuf -lpthread
reader:helloworld.pb.cc reader.cpp
    g++ $^ -o  $@ -l protobuf -lpthread
    

参考了:http://www.cppblog.com/colorful/archive/2012/05/05/173761.html

 $@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。

protobuf 官方只有java、c++、Python的支持。

 

 ----------------------

一个例子:

关于Windows环境下protobuf初步学习指南

http://wenku.baidu.com/link?url=yAY8KF5lLV1LJa_yFwTygoizdUAZDB-l2bLa6IUN79q-xiogW8se1VKew9DIsSAa9o02m7F2XJPFananREd4jrxuUaVhan34Aw7qwGVr61K

 

讲解如何配置vs的:

VS2008下创建一个工程ProtoBuf,需要添加protobuf的头文件和lib文件。 
A.添加头文件操作:右击项目属性配置属性C/C++常规,右边附加包含目录。具体路径:H:\protobuf-2.4.1\protobuf-2.4.1\src 
B.添加库文件(lib)操作:右击项目属性配置属性链接器常规,右边附加库目录。具体路径:H:\protobuf-2.4.1\protobuf-2.4.1\vsprojects\Debug 
把person.pb.h和person.ph.cc放到工程ProtoBuf相应的头文件夹和源文件夹中

 

#include<iostream>
#include"helloworld.pb.h"

#pragma comment(lib,"libprotobuf.lib")
#pragma comment(lib,"libprotoc.lib")

using namespace std;
using namespace Im;


int main(int argc, char **argv)
{
    helloworld msg1;
    msg1.set_id(100);
    msg1.set_str("sd");

    cout << msg1.id();
    cout << msg1.str();

}

如果不想写

#pragma comment(lib,"libprotobuf.lib")
#pragma comment(lib,"libprotoc.lib")

有一种办法,项目配置-》链接器-》输入-》附加依赖性,增加
libprotobuf.lib
libprotoc.lib 也行。

http://my.oschina.net/cxh3905/blog/293000

 
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

google protobuf使用 的相关文章

  • SpringCloudAlibaba实战入门之Dubbo(基于Nacos注册中心)(七)

    一 Dubbo介绍 Dubbo是阿里巴巴公司开源的一个高性能 轻量级的 Java RPC 框架 致力于提供高性能和透明化的 RPC 远程服务调用方案 以及 SOA 服务治理方案 官网 http dubbo apache org 服务提供者在
  • C++11数组了解

    原文链接 C 11数组 array 的使用 码到城攻使用 std array 能够让代码变得更加 现代化 而且封装了一些操作函 数 比如获取数组大小以及检查是否非空https www codecomeon com posts 221 数组介
  • Hadoop NameNode和DataNode只能启动一个问题

    DataNode和NameNode进程不能共存 启动NameNode可以正常启动 但是启动DataNode时发现 NameNode进程不存在了 导致两个无法共存 问题原因 NameNode在format初始化后会生成claserId 集群i
  • Java Web项目部署到Linux后的中文乱码问题

    问题描述 项目通过Maven打成war包传输到Linux上 SQL导出数据和结构后在Linux上的Mysql执行 数据都能正常显示 项目也是正常的访问到了index html 一切显得毫无问题 开始测试项目各个功能是否有异常 当我检查到我的
  • python练习.求s=a+aa+aaa+aaaa+aa...a的值

    题目 求s a aa aaa aaaa aa a的值 其中a是一个数字 例如2 22 222 2222 22222 此时共有5个数相加 几个数相加由键盘控制 from functools import reduce n 0 s n int
  • SegFormer 代码详解+数据流分析

    目录 代码详解 数据流分析 数据流及尺寸变化 输入为512x512x3的图片 使用b0主干网络 Encoder mit backbone Transformer Block 解码头 Head 代码详解 import torch 导入PyTo
  • java内存模型的角度分析volatile关键字

    多任务处理 多任务处理的背景 计算机的运算能力增强 计算机的运算速度与它的存储和通信子系统的速度差距太大 大量的时间都花费在磁盘I O 网络通信或者数据库访问中上 我们不希望处理器在大部分时间里都处于等待其他资源的空闲状态 计算机多任务处理
  • Thymeleaf的常用表达式及简单使用实例

    什么是Thymelaf 它是非常可拓展的 允许自定义名字来定义一组模板属性 或者甚至是标签 它还带有一些称为标准方言的东西 它们定义了一组功能 这些功能满足大多数情况 标准表达式五种类型 变量表达式 选择表达式 消息表达式 i18n 链接表
  • 不使用PCL库,C++保存PLY文件

    输入文件名和TriangulatePoints的结果 void savePLY const std string ply3D filename cv Mat pnts time t t time 0 char tmp1 64 strftim
  • 三因素方差分析_多因变量方差分析和方差成分分析

    点击蓝字关注我们 什么是多因变量方差分析 1 SPSS的一般线性模型中的多变量过程提供多因变量的方差分析 多因变量方差分析模型的因变量是尺度变量 连续变量 分类变量作为固定因素变量 协变量必须是尺度变量 该模型是基于尺度因变量与作为预测因子
  • gre报文长度解析

    pTemp为GRE报文头指针 unsigned char getGreHdrLen unsigned char pTemp unsigned char greflags1 pTemp unsigned char greflags2 pTem
  • poj 3280 Cheapest Palindrome(区间DP)[增删改变简单回文串]

    题目大意 给出一个由n个小写字母组成的 长度为m的字符串字符串来 对这个字符串进行删除字母或者添加字母 使得该字符串是一个回文串 每一步删除和添加每个字母都有对应的代价 求将该字符串转成回文串的最小代价 对于一个串来说在一端删除一个字母和再
  • dy之__ac_signature

    文章目录 目标网站 参数定位 补环境代码 python 测试 往期逆向文章推荐 JS逆向之今日头条signature JS逆向之淘宝sign JS逆向之知乎jsvmp算法 JS逆向之艺恩数据 JS逆向之网易云音乐 JS逆向之巨量星图sign
  • 如何去实践一个完整的数据挖掘项目?

    每日一问 如何去实践一个完整的数据挖掘项目 机器学习项目 1 抽象成数学问题 明确问题 2 获取数据 3 特征预处理与特征选择 4 训练模型与调优 5 模型诊断 6 模型融合 非必须 7 上线运行 大部分机器学习项目死在第1步和第2步 平时
  • Python删除缺失值所在行

    转载 https blog csdn net qq 35843543 article details 106471278 关键内容 data dropna how all 传入这个参数后将只丢弃全为缺失值的那些行 data dropna a
  • python+webdriver解决:web页面大小调整和滚动

    因为页面显示不全导致页面的元素定位失败 可以缩小 滚动web页面把想要定位的元素显示出来 原地址连接 https www cnblogs com wdana p 12037567 html
  • 【目标检测】18、RetinaNet:Focal Loss for Dense Object Detection

    文章目录 一 背景 二 方法 2 1 Focal loss 2 2 RetinaNet 网络结构 三 效果 论文 Focal Loss for Dense Object Detection 代码 https github com faceb
  • mybatis mysql 批量_mysql使用mybatis批量更新问题

    一 好言 在光芒万丈之前 我们都要欣然接受眼下的难堪和不易 接受一个人的孤独和偶尔的无助 二 背景 其实这是在处理一个问题的时候 需要批量更新数据 结果这个批量更新数据是有问题的 所以改了顺便记载下 问题 SQL update t user

随机推荐

  • spring boot版本太高导致Error creating bean with name ‘configurationPropertiesBeans‘ defined in class path

    org springframework beans factory BeanCreationException Error creating bean with name configurationPropertiesBeans defin
  • Acwing算法提高课—搜索

    搜索 BFS Flood Fill AcWing 1097 池塘计数 AcWing 1098 城堡问题 AcWing 1106 山峰和山谷 最短路模型 AcWing 1076 迷宫问题 AcWing 188 武士风度的牛 AcWing 11
  • Unity3d学习之路-简单巡逻兵

    简单巡逻兵 简单巡逻兵 游戏规则与游戏要求 游戏UML类图 游戏实现 巡逻兵部分 巡逻兵预制体 巡逻兵创建 巡逻兵巡逻与追捕 玩家部分 区域部分 订阅与发布模式部分 发布事件类 订阅者 水晶触碰 玩家
  • 2021年 至 2023年 mysql国家法定节假日脚本

    2021年 至 2023年 mysql国家法定节假日脚本 查阅相关资料 根据日历表核对数据 获取2021 2022 2023年数据 建表语句 DROP TABLE IF EXISTS public holiday info CREATE T
  • java代码实现导出或者下载xml、word、pdf、excel功能

    java代码实现导出或者下载xml word pdf excel功能 写在前面 将用户操作日志以xml word pdf excel格式的文件导出 1 导出xml 导出xml使用JAXB的注解实现 实体如下 import javax xml
  • 目标检测——mAP

    mean Average Precision 对于一张图片中的c类目标 算法检测出来 T 个c类的目标 而真值是 TP FN 个c类的目标 检测结果中有 TP 个结果和真值的 IOU 达到某个设定的阈值 那么Precision定义为 对所有
  • 机器学习—使用Gradient Descent预测房价—c++实现

    1 Introduction 之前写了一篇梯度下降的c语言实现 听吴恩达机器学习的入门课 于是考虑自己写一个简易的机器学习的例子 我们打算做一个model为f x W x B这样简单的模型 背景可以理解为房子的面积对应不同的价格 x为房子的
  • BUG:使用/var/log/messages初步定位软件莫名退出问题

    BUG 使用 var log messages定位问题 1 var log 目录下文件和目录简介 var log messages 包括整体系统信息 也包含系统启动期间的日志 此外 mail cron daemon kern和auth等内容
  • 使用谷歌提供的解析插件gsonformat安装到Android studio方法

    转载地址 https www cnblogs com tianmanyi p 6028624 html Android Studio菜单栏File gt Settings gt plugins 这个是Android Studio搜索和安装插
  • C语言——输入两个数,输出较大值(函数调用实现)

    C语言函数调用 输入两个数 要求输出其较大值 一个返回值 两个参数 名字getMaxFromTwoData 函数体 正常实现 三目运算符 函数调用过程 1 在定义函数中指定的形参 在未出现函数调用时 不占用存储单元 发生调用时 函数形参被临
  • 解决Tomcat下IntelliJ IDEA报错java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener

    解决Tomcat下IntelliJ IDEA报错java lang NoClassDefFoundError javax servlet ServletContextListener 笔者在做代码重构的时候 以前记得运行正常的代码 如今一直
  • 解决Pycharm导入模块时提示Cannot find reference

    问题描述 今天在学习python时候遇到了一个导入模块时提醒Cannot find reference 的问题 要导入的这个模块是正常的 解决方案 在pycharm中设置source路径 File gt Setting gt Project
  • 数据结构与算法Python版期末在线考试OJ部分

    1 二叉树路径 10分 题目内容 给定一个二叉查找树的节点插入顺序 请重新构建这个二叉查找树 并按从左至右顺序返回所有根节点至叶节点的路径 输入格式 一行整数 以空格分隔 注 测试用例中不包含重复的数字 输出格式 按照叶节点由左至右顺序 以
  • 【亲测可用】使用pm2部署nuxt项目

    1 科普 Nuxt是一个基于vue js的应用框架 可以做到服务器端渲染 解决vue动态生成页面 难以SEO优化的难题 详情我这里不赘述了 想要了解的可以查看这里 Nuxt教程 PM2是一个进程管理工具 用于启动 维护Node的应用程序 非
  • Finalshell连接Linux超时之Connection timed out: connect

    BUG原因 每次重启finalshell 还是 CentOS ip地址存在变化的可能 目录 前言 报错 摸索 解决措施 前言 1 福利 花了2小时才解决的BUG 希望本篇文章能帮你10分钟解决 2 tips ipconfig或ip addr
  • cp can‘t stat ..........

    在我把usr src linux source 5 13 0 tar bz2复制的时候出现了错误 就是这个提示 cp cannot stat linux source 5 13 0 tar bz2 No such file or direc
  • Linux性能调优之sar详解

    什么是sar sar是一个采集 报告和存储计算机负载信息的工具 有的时候 我们要通过对系统的cpu负载等性能数值的查看 来判排查系统产生某种故障 经常死机或者运行速度突然变慢 的原因 但是 简单的top uptime w等命令只可以查看当前
  • linux :ubuntu 安装搜狗输入法

    1 安装Fcitx输入框架 sudo apt install fcitx 2 搜狗输入法官网下载Linux版本搜狗输入法 32位和64位根据自己情况 3 输入指令安装 sudo dpkg i sogoupinyin 2 3 1 0112 a
  • 虚拟机的内存泄漏和内存溢出

    文章目录 内存泄漏 内存溢出 集合引起的内存泄漏 内存泄漏 内存泄漏的根本原因是长生命周期的对象持有短生命周期对象的引用 尽管短生命周期的对象已经不再需要 但由于长生命周期对象持有它的引用而导致不能被回收 以发生的方式来分类 内存泄漏可以分
  • google protobuf使用

    http www cnblogs com youxin p 4073703 html If you get the source from github you need to generate the configure script f