PB协议 初体验

写在前面

基于项目需要,初体验PB协议。本文及后续文章的实操均是在window环境,C++语言。文章所述均会依据PB官网,一些语言无关的描述(例如.proto介绍)可供所有平台、语言环境参考。

一 什么是PB

Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. You can even update your data structure without breaking deployed programs that are compiled against the "old" format.

翻译: ProtocolBuffer是用于序列化结构数据的灵活、高效、自动的方法,有如XML,不过它更小、更快、也更简单。一旦定义了你自己的数据结构,然后就可以使用特殊生成的源代码轻松的在各种数据流和使用的各种高级语言之间读写你的结构化数据。你甚至可以在不破坏根据“旧”格式编译的已部署程序的情况下更新你的数据结构。

(Protocol buffers are Google's language-neutral, platform-neutral……谷歌的,与平台、语言无关……)。

二 支持语言

Protocol buffers currently support generated code in Java, Python, Objective-C, and C++. With our new proto3 language version, you can also work with Go, Ruby, and C#, with more languages to come.

三 下载

点击 下载地址

我下载的是protoc-3.6.1-win32,目前(2018.11.05)最新release版,然后解压缩。

四 简单使用

1 编写.proto文件

现在的proto有两个版本proto2和proto3,proto3在语法上发生了一些改变,查找的资料中很多还是使用的proto2语法。

我的demo.proto内容如下:

syntax = "proto3";

package demo;
message Person {
    string name = 1;
    int32 id = 2;
    string email = 3;

    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }

    message PhoneNumber {
        string number = 1;
        PhoneType type = 2;
    }
    repeated PhoneNumber phone = 4;
}

放置位置,我直接放在了protoc.exe的旁边,如下:

2 生成C++文件

一个.proto文件生成一个.hh .cc文件。

打开cmd, cd到该目录,protoc.exe的命令行参数格式如下:

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR path/to/file.proto

我的操作见下图:

运行命令后见下图:

部分demo.pb.h的内容感受下:

namespace demo {
……
class Person : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:demo.Person) */ {
public:
    Person();
    virtual ~Person();

    Person(const Person& from);

    inline Person& operator=(const Person& from) {
        CopyFrom(from);
        return *this;
    }
#if LANG_CXX11
    Person(Person&& from) noexcept
    : Person() {
        *this = ::std::move(from);
    }

    inline Person& operator=(Person&& from) noexcept {
        if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
            if (this != &from) InternalSwap(&from);
            } else {
                CopyFrom(from);
        }
        return *this;
    }
#endif
    static const ::google::protobuf::Descriptor* descriptor();
    static const Person& default_instance();

    static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
    static inline const Person* internal_default_instance() {
    return reinterpret_cast<const Person*>(
        &_Person_default_instance_);
    }
    static constexpr int kIndexInFileMessages = 1;

    void Swap(Person* other);
    friend void swap(Person& a, Person& b) {
        a.Swap(&b);
    }
……

注意代码中的几个地方:

(1)proto中的package在C++中是namespace;

(2)proto中的message在C++中是class,类里面有各个成员的set/get;基类是google::protobuf::Message。

(3)代码中可以看见C++11中的移动构造和移动赋值函数。

五 序列化和反序列化

基本上可以猜到相关接口是在基类中定义的,这里直接用一个官网最简单的例子:

message Foo {
    string text = 1;
    repeated int32 numbers = 2;
}

string data;  // Will store a serialized version of the message.

{
    // Create a message and serialize it.
    Foo foo;
    foo.set_text("Hello World!");
    foo.add_numbers(1);
    foo.add_numbers(5);
    foo.add_numbers(42);

    foo.SerializeToString(&data);
}

{
    // Parse the serialized message and check that it contains the
    // correct data.
    Foo foo;
    foo.ParseFromString(data);

    assert(foo.text() == "Hello World!");
    assert(foo.numbers_size() == 3);
    assert(foo.numbers(0) == 1);
    assert(foo.numbers(1) == 5);
    assert(foo.numbers(2) == 42);
}

从PB的定义中可以知道数据流不止string一种,还有很多其他的类型,也就是还有很多其他的序列化反序列化接口。

 有兴趣可以在下载那里下载一份protobuf-cpp-3.6.1(C++的),里面有源码。

六 资料

官网

Github

开源中国-PB

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值