gRPC快速入门(三)——Protobuf应用示例
一、Protobuf使用流程
在工程开发中使用Protobuf流程如下:
(1)定义proto描述文件,以proto作为后缀名。
(2)使用Protobuf编译器protoc来生成编程语言代码文件,对消息格式以特定的语言方式描述。
(3)使用Protobuf库提供的API来编写应用程序 。
二、Protobuf C++示例
1、环境变量设置
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/protobuf/lib
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/protobuf/lib
export PATH=$PATH:/usr/local/protobuf/bin
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
2、定义proto文件
addressbook.proto文件如下:
// [START declaration]
syntax = "proto3";
package Book;
import "google/protobuf/timestamp.proto";
// [END declaration]
// [START messages]
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
// [END messages]
3、生成C++代码
protoc --cpp_out=. addressbook.proto
生成C++代码addressbook.pb.h和addressbook.pb.cc。
addressbook.pb.h文件:
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: addressbook.proto
#ifndef PROTOBUF_INCLUDED_addressbook_2eproto
#define PROTOBUF_INCLUDED_addressbook_2eproto
#include <string>
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3006001
#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 3006001 < 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/io/coded_stream.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_table_driven.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/inlined_string_field.h>
#include <google/protobuf/metadata_lite.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
#include <google/protobuf/extension_set.h> // IWYU pragma: export
#include <google/protobuf/generated_enum_util.h>
#include <google/protobuf/timestamp.pb.h>
// @@protoc_insertion_point(includes)
#define PROTOBUF_INTERNAL_EXPORT_protobuf_addressbook_2eproto
namespace protobuf_addressbook_2eproto {
// Internal implementation detail -- do not use these members.
struct TableStruct {
static const ::google::protobuf::internal::ParseTableField entries[];
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
static const ::google::protobuf::internal::ParseTable schema[3];
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
static const ::google::protobuf::internal::SerializationTable serialization_table[];
static const ::google::protobuf::uint32 offsets[];
};
} // namespace protobuf_addressbook_2eproto
namespace book {
class AddressBook;
class AddressBookDefaultTypeInternal;
extern AddressBookDefaultTypeInternal _AddressBook_default_instance_;
class Person;
class PersonDefaultTypeInternal;
extern PersonDefaultTypeInternal _Person_default_instance_;
class Person_PhoneNumber;
class Person_PhoneNumberDefaultTypeInternal;
extern Person_PhoneNumberDefaultTypeInternal _Person_PhoneNumber_default_instance_;
} // namespace book
namespace google {
namespace protobuf {
template<> ::book::AddressBook* Arena::CreateMaybeMessage<::book::AddressBook>(Arena*);
template<> ::book::Person* Arena::CreateMaybeMessage<::book::Person>(Arena*);
template<> ::book::Person_PhoneNumber* Arena::CreateMaybeMessage<::book::Person_PhoneNumber>(Arena*);
} // namespace protobuf
} // namespace google
namespace book {
enum Person_PhoneType {
Person_PhoneType_MOBILE = 0,
Person_PhoneType_HOME = 1,
Person_PhoneType_WORK = 2,
Person_PhoneType_Person_PhoneType_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,
Person_PhoneType_Person_PhoneType_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max
};
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;
// ===================================================================
class Person_PhoneNumber : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:book.Person.PhoneNumber) */ {
public:
Person_PhoneNumber();
virtual ~Person_PhoneNumber();
Person_PhoneNumber(const Person_PhoneNumber& from);
inline Person_PhoneNumber& operator=(const Person_PhoneNumber& from) {
CopyFrom(from);
return *this;
}
#if LANG_CXX11
Person_PhoneNumber(Person_PhoneNumber&& from) noexcept
: Person_PhoneNumber() {
*this = ::std::move(from);
}
inline Person_PhoneNumber& operator=(Person_PhoneNumber&& from) noexcept {
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
if (this != &from) InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
#endif
static const Person_PhoneNumber& default_instance();
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const Person_PhoneNumber* internal_default_instance() {
return reinterpret_cast<const Person_PhoneNumber*>(
&_Person_PhoneNumber_default_instance_);
}
static constexpr int kIndexInFileMessages =
0;
void Swap(Person_PhoneNumber* other);
friend void swap(Person_PhoneNumber& a, Person_PhoneNumber& b) {
a.Swap(&b);
}
// implements Message ----------------------------------------------
inline Person_PhoneNumber* New() const final {
return CreateMaybeMessage<Person_PhoneNumber>(NULL);
}
Person_PhoneNumber* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Person_PhoneNumber>(arena);
}
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)
final;
void CopyFrom(const Person_PhoneNumber& from);
void MergeFrom(const Person_PhoneNumber& from);
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const final;
void DiscardUnknownFields();
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(Person_PhoneNumber* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return NULL;
}
inline void* MaybeArenaPtr() const {
return NULL;
}
public:
::std::string GetTypeName() const final;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// string number = 1;
void clear_number();
static const int kNumberFieldNumber = 1;
const ::std::string& number() const;
void set_number(const ::std::string& value);
#if LANG_CXX11
void set_number(::std::string&& value);
#endif
void set_number(const char* value);
void set_number(const char* value, size_t size);
::std::string* mutable_number();
::std::string* release_number();
void set_allocated_number(::std::string* number);
// .book.Person.PhoneType type = 2;
void clear_type();
static const int kTypeFieldNumber = 2;
::book::Person_PhoneType type() const;
void set_type(::book::Person_PhoneType value);
// @@protoc_insertion_point(class_scope:book.Person.PhoneNumber)
private:
::google::protobuf::int