C++ protobuf如何为嵌套结构设置值

C++ protobuf how to set values for nested struct

我正在学习 C++ ProtoBuf。

我有以下需要序列化的结构:

enum phonetype
{
    DESKPHONE,
    MOBILE,
    WIRELESSPHONE
};

struct phonenumber
{
    int ptype;
    string number;
};

struct address
{
    string addr1;
    string addr2;
};

struct college
{
    string collegename;
    string collegeaddress;
};

struct student
{
    int id;
    string name;
    double age;
    string email;

    struct phonenumber phoneN;
    struct address addr;
    struct college col;
};

我已经初始化结构如下:

student stud = {123, "Stud_1", 30, "none",
                    {MOBILE, "123456789"}, 
                    {"Boston, US", "None"}, 
                    {"Boston college", "Boston"}};

现在我想创建这个结构的序列化字符串,我为此编写了以下 .proto 文件:

syntax = "proto2";

message studentP
{
  required int32 id = 1;
  required string name = 2;
  required double age = 3;
  optional string email = 4;

  message phonenumberP
  {
    required int32 ptype = 1;
    required string number = 2;
  }
  
  message addressP {
    required string addr1 = 1;
    optional string addr2 = 2;
  }

  message collegeP {
    required string collegename = 1;
    optional string collegeaddress = 2;
  }  
}

在我的 C++ 代码中,我将 proto obj 值设置如下:

studentP studObj;
studObj.set_name(stud.name);
studObj.set_eid(stud.id);
studObj.set_age(stud.age);

studentP::phonenumberP *phone;
phone->set_ptype(stud.phoneN.ptype);
phone->set_number(stud.phoneN.number);

studentP::addressP *addr;
addr->set_addr1(stud.addr.addr1);
addr->set_addr2(stud.addr.addr2);

studentP::collegeP *coll;
coll->set_collegename(stud.col.collegename);
coll->set_collegeaddress(stud.col.collegeaddress);


string student_str;
studObj.SerializeToString(&student_str);

上面我分别设置了classstudentP.

的内部结构的值

如何设置 studentP 对象 studObj 的内部结构的值?

我需要为每个内部结构调用 SerializeToString 吗?

截至目前,您的 ProtoBuf 模式仅包含嵌套消息(phone、地址和大学)的定义;但是,不是它们各自在 Student 消息类型中的字段。而且,您不需要在代码中使用单独的结构。它们已经在 protoc 生成的 .pb.h.pb.cc 文件中声明和定义。使用那些。否则,除非您有充分的理由这样做,否则在使用已经为您维护的 serialization/deserialization library/framework 的同时在代码中手动维护这些类型将是弄巧成拙。

更新后的 ProtoBuf 架构将是(观察下面的字段 5、6 和 7):

studentinfo.proto

syntax = "proto2";

package test;

message Student
{
    required int32 id = 1;
    required string name = 2;
    required double age = 3;
    optional string email = 4;

    enum PhoneType
    {
        DESK = 1;
        MOBILE = 2;
        WIRELESS = 3;
    };

    message Phone
    {
        required PhoneType type = 1;
        required string number = 2;
    }

    message Address {
        required string address1 = 1;
        optional string address2 = 2;
    }

    message College {
        required string name = 1;
        optional string address = 2;
    }

    required Phone phone = 5;
    required Address address = 6;
    optional College college = 7;
}

一旦您拥有所需的架构和生成的文件,您就可以继续创建和填充类型,然后序列化消息以通过网络发送并在另一端反序列化。

这是一个完整的工作示例:

main.cpp

#include <iostream>
#include <string>
#include "studentinfo.pb.h"

int main()
{
    using namespace test;

    // Serialization

    Student s;
    s.set_name("Test");
    s.set_id(123);
    s.set_age(24);

    s.mutable_phone()->set_type(Student_PhoneType_DESK);
    s.mutable_phone()->set_number("+00 123 1234567");

    s.mutable_address()->set_address1("House # 1, Street # 1");
    s.mutable_address()->set_address2("House # 2, Street # 2");

    s.mutable_college()->set_name("XYZ College");
    s.mutable_college()->set_address("College Address Here");

    std::cout << "Serialization:\n\n" << s.DebugString() << "\n\n";
    //s.PrintDebugString();

    std::string serialized;
    if ( !s.SerializeToString( &serialized ) )
    {
        std::cerr << "ERROR: Unable to serialize!\n";
        return -1;
    }

    // Deserialization

    Student deserialized;
    if ( !deserialized.ParseFromString( serialized ) )
    {
        std::cerr << "ERROR: Unable to deserialize!\n";
        return -1;
    }

    std::cout << "Deserialization:\n\n";
    deserialized.PrintDebugString();

    // deserialized.name();
    // deserialized.id();
    // ...
    // deserialized.phone().type();
    // deserialized.phone().number()
    // ...

    return 0;
}

输出:

Serialization:

id: 123
name: "Test"
age: 24
phone {
  type: DESK
  number: "+00 123 1234567"
}
address {
  address1: "House # 1, Street # 1"
  address2: "House # 2, Street # 2"
}
college {
  name: "XYZ College"
  address: "College Address Here"
}


Deserialization:

id: 123
name: "Test"
age: 24
phone {
  type: DESK
  number: "+00 123 1234567"
}
address {
  address1: "House # 1, Street # 1"
  address2: "House # 2, Street # 2"
}
college {
  name: "XYZ College"
  address: "College Address Here"
}

查看 .pb.h 文件,了解您可能需要处理消息的修改器和访问器。