• 07_c/c++开源库protobuf序列化


    1.简介与安装

    简介: 无, 懂的都懂

    安装

    sudo apt install protobuf-compiler protobuf-c-compiler libprotobuf-dev

    编译依赖

    pkg-config --cflags --libs protobuf

    -pthread -lprotobuf -pthread

    编译选项: -pthread
    链接选项: -lprotobuf -pthread

    2.实例

    1.代码

    实例1

    addressbook.proto

    syntax = "proto3";
    
    package tutorial;
    
    message Person {
      string name = 1;
      string email = 2;
    }
    
    message AddressBook {
      repeated Person people = 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    1_addressbook_protobuf实例.cc

    #include 
    #include 
    #include 
    #include "addressbook.pb.h"
    
    void WriteAddressBook()
    {
        tutorial::AddressBook address_book;
    
        // 添加一个 Person
        tutorial::Person *person = address_book.add_people();
        person->set_name("Alice");
        person->set_email("alice@example.com");
    
        // 写入到文件
        std::ofstream output("addressbook.data", std::ios::binary);
        if (!address_book.SerializeToOstream(&output))
        {
            std::cerr << "Failed to write address book." << std::endl;
            return;
        }
    }
    
    void ReadAddressBook()
    {
        tutorial::AddressBook address_book;
    
        // 从文件读取
        std::ifstream input("addressbook.data", std::ios::binary);
        if (!address_book.ParseFromIstream(&input))
        {
            std::cerr << "Failed to read address book." << std::endl;
            return;
        }
    
        // 输出读取到的人名
        for (int i = 0; i < address_book.people_size(); ++i)
        {
            const tutorial::Person &person = address_book.people(i);
            std::cout << "Name: " << person.name() << ", Email: " << person.email() << std::endl;
        }
    }
    
    int main()
    {
        WriteAddressBook();
        ReadAddressBook();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    实例2

    person.proto

    syntax = "proto3";  // 使用Protocol Buffers v3语法
    
    package example;  // 定义包名,便于组织和避免命名冲突
    
    message Person {  // 定义名为Person的消息类型
      string name = 1;  // 字符串类型字段,标签为1
      int32 id = 2;    // 整型字段,标签为2
      bool is_active = 3;  // 布尔型字段,标签为3
      repeated string email = 4;  // 重复字段,表示字符串列表,标签为4
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2_protobuf_person_序列号到字节.cc

    #include "person.pb.h"
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    // 写入文件
    void WriteToFile(const std::string& filename, const example::Person& person) {
      std::fstream output(filename, std::ios::out | std::ios::trunc | std::ios::binary);
      if (!person.SerializeToOstream(&output)) {
        std::cerr << "Failed to write person." << std::endl;
      }
    }
    
    // 从文件读取
    void ReadFromFile(const std::string& filename, example::Person& person) {
      std::fstream input(filename, std::ios::in | std::ios::binary);
      if (!person.ParseFromIstream(&input)) {
        std::cerr << "Failed to parse person." << std::endl;
      }
    }
    
    // 打印反序列化后的数据
    void PrintPerson(const example::Person& person) {
      std::cout << "Name: " << person.name() << std::endl;
      std::cout << "ID: " << person.id() << std::endl;
      std::cout << "Is Active: " << person.is_active() << std::endl;
      // 打印反序列化后的数据
      for (int i = 0; i < person.email_size(); ++i) {
        std::cout << "Email " << i + 1 << ": " << person.email(i) << std::endl;
      }
    }
    
    int main() {
      // 创建并填充一个Person对象
      example::Person person;
      person.set_name("Alice");
      person.set_id(123);
      person.set_is_active(true);
      person.add_email("alice@example.com");
      person.add_email("alice.personal@gmail.com");
    
      // 1.序列化到 字节
      uint8_t buf[256] = { 0 };
      bool ret = person.SerializeToArray(buf, sizeof(buf));
    
      // 2.反序列化从 字节
      example::Person new_person;
      ret = new_person.ParseFromArray(buf, sizeof(buf));
    
      cout << "result ret: " << ret << endl;
      PrintPerson(new_person);
    
      // 3.读写probuf测试
      WriteToFile("person.bin", person);  // 写入文件
      ReadFromFile("person.bin", new_person); // 从文件读取
      PrintPerson(new_person);            // 打印反序列化后的数据
    
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    2.scons编译

    SConstruct

    import os
    ## 模板2
    env = Environment()
    env["PROGSUFFIX"] = ".out"            # 可执行后缀.out
    env["CCFLAGS"] = " -g3 -O0 -Wall"       # gdb 调试开关
    # -pthread -lprotobuf
    env.MergeFlags(["!pkg-config protobuf --cflags --libs"])
    
    def build_protobuf(file_path):
        file,file_ext = os.path.splitext(file_path)
        print(file,file_ext)
        if file_ext != ".proto":
            raise f"{file_path} not .proto file"
        cmd=f"protoc --cpp_out=. {file}.proto"
        Command(f"{file}.pb.h",file_path,cmd)
    
    build_protobuf("addressbook.proto")
    env.Program(Split("1_addressbook_protobuf实例.cc addressbook.pb.cc"))
    build_protobuf("person.proto")
    env.Program(Split("2_protobuf_person_序列号到字节.cc person.pb.cc"))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    注意:
    protobuf编译方法
    protoc --cpp_out=. addressbook.proto

    生成 addressbook.pb.cc addressbook.pb.h

    scons中并没有直接构建protobuf方法, 可以使用scons Command(target_file, src_file, cmd)
    Command使用说明: 如果src_file 时间戳比 target_file 新, 则执行cmd命令
    示例: Command("addressbook.pb.h", "addressbook.proto", "rotoc --cpp_out=. addressbook.proto")


    scons

    scons: Reading SConscript files …
    addressbook .proto
    person .proto
    scons: done reading SConscript files.
    scons: Building targets …
    protoc --cpp_out=. addressbook.proto
    g++ -o 1_addressbook_protobuf实例.o -c -g3 -O0 -Wall -pthread 1_addressbook_protobuf实例.cc
    g++ -o addressbook.pb.o -c -g3 -O0 -Wall -pthread addressbook.pb.cc
    g++ -o 1_addressbook_protobuf实例.out -pthread 1_addressbook_protobuf实例.o addressbook.pb.o -lprotobuf
    protoc --cpp_out=. person.proto
    g++ -o 2_protobuf_person_序列号到字节.o -c -g3 -O0 -Wall -pthread 2_protobuf_person_序列号到字节.cc
    g++ -o person.pb.o -c -g3 -O0 -Wall -pthread person.pb.cc
    g++ -o 2_protobuf_person_序列号到字节.out -pthread 2_protobuf_person_序列号到字节.o person.pb.o -lprotobuf
    scons: done building targets.

    3.验证测试

    ./1_addressbook_protobuf实例.out

    Name: Alice, Email: alice@example.com

    ./2_protobuf_person_序列号到字节.out

    result ret: 0
    Name: Alice
    ID: 123
    Is Active: 1
    Email 1: alice@example.com
    Email 2: alice.personal@gmail.com
    Name: Alice
    ID: 123
    Is Active: 1
    Email 1: alice@example.com
    Email 2: alice.personal@gmail.com

    3.其它实例

    gitee 在线代码


  • 相关阅读:
    MSE 治理中心重磅升级-流量治理、数据库治理、同 AZ 优先
    记录一次成功的frida编译
    老牌期货公司综合实力强开户体验佳
    在ubuntu用wine安装微信 并解决无法输入文字的问题 ubuntu完美安装微信
    【navicat 密码查看】小技巧navicat 如何查看密码
    湖南省内中高风险地区来长参加成考考生必须进行报备
    c语言进阶篇:指针(一)
    两台linux虚拟机之间实现免密登录
    Nginx的安装及启动【编译安装+Docker拉取安装(开发时首选)】
    “深入理解机器学习性能评估指标:TP、TN、FP、FN、精确率、召回率、准确率、F1-score和mAP”
  • 原文地址:https://blog.csdn.net/u011326325/article/details/138144955