简介

  • protobuf库 笔记

C++ protobuf是什么

Protocol Buffers(ProtoBuf)是由Google开发的一种轻量级、高效的数据交换格式,同时也是一种用于序列化结构化数据的协议。ProtoBuf 可以被用于多种应用场景,最常见的是在数据通信和数据存储中。

以下是对 Protocol Buffers 的一些主要特点和用法的解释:

主要特点:

  1. 可读性和可扩展性: ProtoBuf 使用二进制格式,相比于 XML 和 JSON 等文本格式,更加紧凑、高效。尤其在大规模数据传输场景下,ProtoBuf 的性能更为优越。

  2. 数据结构定义: 使用简洁的语法定义结构化的数据模型。定义的数据结构称为消息(Message),通过 Protobuf 编译器生成对应的代码,用于序列化和反序列化数据。

    1
    2
    3
    4
    5
    6
    7
    
     syntax = "proto3";
    
     message Person {
       required string name = 1;
       required int32 id = 2;
       optional string email = 3;
     }
    
  3. 跨语言支持: ProtoBuf 生成的代码支持多种编程语言,包括 C++, Java, Python, Go, Ruby, C#, JavaScript 等,使得数据在不同平台和语言间的交换变得简便。

  4. 版本兼容性: ProtoBuf 具有向前和向后兼容性,允许在不破坏现有数据的情况下进行协议的演化。

  5. 高性能: 序列化和反序列化速度快,占用的存储空间相对较小,适用于对性能有要求的场景。

使用步骤:

  1. 定义消息: 使用 Protocol Buffers 的语法定义消息的数据结构。

    1
    2
    3
    4
    5
    6
    7
    
     syntax = "proto3";
    
     message Person {
       required string name = 1;
       required int32 id = 2;
       optional string email = 3;
     }
    
  2. 编译器生成代码: 使用 Protobuf 编译器(protoc)将消息定义文件编译为相应语言的代码。

    1
    
     protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/person.proto
    
  3. 使用生成的代码: 在程序中使用生成的代码进行消息的序列化和反序列化。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
     // 使用生成的代码
     #include "person.pb.h"
    
     // 创建 Person 对象
     Person person;
     person.set_name("John");
     person.set_id(123);
    
     // 序列化为字节流
     std::string serialized_data = person.SerializeAsString();
    
     // 反序列化
     Person deserialized_person;
     deserialized_person.ParseFromString(serialized_data);
    

ProtoBuf 提供了简单、高效、可扩展的数据交换格式,广泛用于网络通信、存储、配置文件等场景。其优秀的性能和跨语言支持使得它成为许多大型项目和分布式系统中的首选数据格式。

C++ protobuf 详解

Protocol Buffers(ProtoBuf)是一种由Google设计的轻量级、高效的数据交换格式。它不仅用于定义数据结构,还提供了一种机制来序列化和反序列化这些数据。在 C++ 中,ProtoBuf 的使用涉及定义 .proto 文件、使用 Protocol Buffers 编译器(protoc)生成代码,以及在代码中使用生成的代码进行序列化和反序列化。

以下是使用 C++ 的 ProtoBuf 的基本步骤:

步骤 1:定义 .proto 文件

首先,定义一个 .proto 文件来描述你的数据结构。例如,下面是一个简单的示例:

1
2
3
4
5
6
7
syntax = "proto3";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
}

在这个示例中,定义了一个 Person 消息,包含 nameid 和可选的 email 字段。

步骤 2:使用 protoc 编译器生成代码

使用 protoc 编译器将 .proto 文件编译成相应语言的代码。在 C++ 中,你需要生成 C++ 代码,可以使用以下命令:

1
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/person.proto

其中,$SRC_DIR 是存放 .proto 文件的目录,$DST_DIR 是生成的 C++ 代码存放的目录。

步骤 3:使用生成的代码

在你的 C++ 代码中,使用生成的代码进行序列化和反序列化。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "person.pb.h"

int main() {
    // 创建 Person 对象
    Person person;
    person.set_name("John");
    person.set_id(123);

    // 序列化为字节流
    std::string serialized_data = person.SerializeAsString();

    // 反序列化
    Person deserialized_person;
    deserialized_person.ParseFromString(serialized_data);

    // 使用反序列化后的数据
    std::cout << "Name: " << deserialized_person.name() << std::endl;
    std::cout << "ID: " << deserialized_person.id() << std::endl;
    std::cout << "Email: " << deserialized_person.email() << std::endl;

    return 0;
}

在这个示例中,我们使用生成的 person.pb.h 头文件中的 Person 类进行数据的操作。SerializeAsString() 方法用于将对象序列化为字符串,而 ParseFromString() 方法用于从字符串中反序列化对象。

注意事项:

  • 字段规则: ProtoBuf 支持的字段规则包括 requiredoptionalrepeated。在 ProtoBuf 3 中,required 已经被废弃,建议使用 optionalrepeated

  • 默认值: ProtoBuf 支持给字段设置默认值。在序列化时,如果字段的值等于默认值,则不会写入到输出流中。

  • 扩展性: ProtoBuf 具有良好的扩展性,可以通过扩展消息和字段来进行协议的演化,同时保持向前和向后兼容性。

  • 更多特性: ProtoBuf 还支持枚举、嵌套消息、扩展等高级特性,可以根据具体需求进行使用。

总体而言,ProtoBuf 提供了一种高效、紧凑、可扩展的数据交换格式,适用于各种场景,特别是对性能和数据大小有要求的应用程序。