如何使用 protobuf 对多个可区分的项目进行背靠背编码?

How to encode multiple distinguishable items back to back with protobuf?

所以,我有一个单元测试,我试图确保编码和解码是正确的。基本上,我有点希望能够将多个不同的 C++ 对象序列化为一个字符串,然后将该字符串写入一个文件。这是我目前所拥有的:

这是我的 .proto 文件:

message Register {
    required string regname = 1;
    required uint64 regvalue = 2;
}

message RegisterContext {
    repeated Register elem = 1;
}

message MemoryRegion {
    repeated bytes elem = 1;
}

message Image {
    required string imgName = 1;
    required MemoryRegion Memory = 2;
    required uint64 MemStart = 3;
    required uint64 MemEnd = 4;
    required bool isMain = 5;
}

message MemoryRegions {
    repeated Image elem = 1;
}

message MemoryDump {
    required RegisterContext context = 1;
    required MemoryRegions state = 2;
}

我有语言白话风格表示对象,可以帮助我像往常一样使用它们:

//name, value
using reg=std::tuple<std::string, uint64_t>;
using reg_context=std::list<reg >;
using mem_region=std::string;
//name, memory, start, end, ismain
using image=std::tuple<std::string, mem_region, uint64_t, uint64_t, bool>;
using mem_region_set=std::list<image >;
using memory_dump=std::tuple<reg_context, mem_region_set>;

这是失败的测试:

TEST(SerializationTests, test_contiguous_memory_differentiated) {
  mem_region region="\x25\x26\x27";
  image i1{std::make_tuple(std::string("img1"), region, 0, 1, false)},
    i2{std::make_tuple(std::string("img2"), region+"\x28", 0, 1, false)},
      i3{std::make_tuple(std::string("img3"), region+"\x29", 0, 1, false)};
  mem_region_set regions1{i1, i2, i3}, regions2{i1, i3};
  auto serialized_regions1=serialize_memory_regions(regions1);
  auto serialized_regions2=serialize_memory_regions(regions2);
  std::stringstream ss;
  ss << *serialized_regions1 << *serialized_regions2;
  auto concatenated=ss.str();
  auto deserialized_region1=unpack_memory_regions(concatenated);
  ASSERT_EQ(deserialized_region1, regions1);
  auto deserialized_region2=unpack_memory_regions(concatenated);
  ASSERT_EQ(deserialized_region2, regions2);
}

如何序列化多个对象,以便无论我将它们放入字符串流还是 ofstream,它们返回时都是独立的? 我 运行 这里的结果是 deserialized_region1/2 每个都有 5 张图片,只有 i1, i2, i3, i1, i3

一种可能的方法是在每个 protobuf 对象之前写入固定的 32 字节整数大小。当您需要解析包含多个对象的缓冲区或文件时,您可以先读取消息长度,然后读取 length 字节长的消息体并解析它。例如,您的消息 MemoryDump 将被编译为 class MemoryDump。你可以这样打包:

MemoryDump memoryDump;
fillData(memoryDump); // put data in it somehow
auto size = memoryDump.ByteSize(); // return space that it needs to be packed
std::string buffer;
StringOutputStream stream(&buffer);
CodedOutputStream coded(&stream);
coded.WriteLittleEndian32(size);
memoryDump.SerializeToCodedStream(&coded);
coded.WriteLittleEndian32(size);
memoryDump.SerializeToCodedStream(&coded);

然后当您解压数据时,您可以:

MemoryDump memoryDump1;
MemoryDump memoryDump2;
std::string buffer;
readBuffer(buffer);
StringInputStream stream(&buffer);
CodedInputStream coded(&stream);
int size;
coded.ReadLittleEndian32(&size);
memoryDump1.ParseFromBoundedZeroCopyStream(&stream, size);
coded.ReadLittleEndian32(&size);
memoryDump1.ParseFromBoundedZeroCopyStream(&stream, size);