google protobuf使用

 

下載的是github上的:https://github.com/google/protobufhtml

 

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

$ ./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.ios

運行這個會下載gtest(google單元測試框架)。因爲google訪問不了,這個這個沒有成功。c++

 

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

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 則說明安裝成功!
若是出現錯誤:github

 

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/libshell

 

 安裝完成後在終端下執行express

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

  打開配置文件,在該文件中添加vim

  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++入門

一、在.proto文件中定義消息格式

二、使用protobuf編譯器
三、使用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?
 
一、原始內存數據結構,能夠以二進制方式sent/saved.這種方式須要相同的內存佈局和字節序。
二、以ad-hoc方式將數據項編碼成一個簡單字符串----好比,將4個int類型編碼成"12:3:-23:67"。這種方式簡靈活。適用於簡單數據。
三、將數據序列化爲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;

}

 

 

 
 
一、定義協議格式
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值必須對應,不然反序列化會出現意想不到的問題。

二、編譯你的協議
 
運行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
 
三、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();

四、枚舉與嵌套類

 
生成的代碼包含一個PhoneType枚舉。Person::PhoneType, Person:MOBILE, Person::HOME, Person:WORK.
 
編譯器生成的嵌套類稱爲Person::PhoneNumber. 實際生成類爲Person_PhoneNumber.
 
五、標準方法
 

bool IsInitialized() const:                確認required字段是否被設置

string DebugString() const:                返回消息的可讀表示,用於調試

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

void Clear():                              清除全部元素爲空狀態

六、解析與序列化
 

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中解析出消息

七、protobuf和 oo設計
不要繼承生成類並在此基礎上添加相應的行爲
 
八、寫消息
 
示例:它從一個文件中讀取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()。
 
九、讀消息 
#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

十、擴展protobuf
 
若是但願向後兼容,必須遵循:
a、沒必要更改tag數
b、沒必要添加或刪除任何required字段
c、能夠刪除optional或repeated字段
d、能夠添加新的optional或repeated字段,但你必須使用新的tag數。
 
十一、優化
c++的protobuf庫,已經極大地優化了。合理使用能夠改善性能。
a、若是可能,複用message對象。
b、關於多線程的內存分配器
 
十二、高級用法
 
protobuf的消息類的一個關鍵特性是, 反射(reflection)。可使用xml或json來實現。 參考
 
 
================================================================
常見問題:
一、undefined reference to `pthread_once' 
使用-lpthread:
 
二、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

 
 
相關文章
相關標籤/搜索