29

在我的服务器上,我们收到自我描述的消息(定义在这里......顺便说一句,这并不是那么容易,因为在 c++ 中没有任何“好的”例子)。

在这一点上,我从这些自我描述的消息中创建消息没有问题。我可以使用 FileDescriptorSet,遍历每个FileDescriptorProto,将每个添加到 DescriptorPool(使用BuildFile,它也给了我每个定义的 FileDescriptor)。

从这里我可以创建在 FileDescriptorSet 中定义的任何消息,其中使用 DP 实例化的 DynamicMessageFactory 并调用GetPrototype(这很容易做到,因为我们的 SelfDescribedMessage 需要消息 full_name(),因此我们可以调用FindMessageTypeByName方法DP,给我们正确编码的消息原型)。

问题是如何获取每个已定义的描述符或消息并动态构建一个“主”消息,其中包含所有已定义消息作为嵌套消息。这主要用于保存消息的当前状态。目前我们只是通过在服务器中实例化每条消息的一种类型来处理这个问题(以保持不同程序的中心状态)。但是当我们想要“保存”当前状态时,我们被迫将它们流式传输到此处定义的磁盘。它们一次流式传输一条消息(带有大小前缀)。我们希望有一条消息(一条来统治所有消息)而不是稳定的单独消息流。一旦解决,这可以用于其他事情(基于网络的共享状态,经过优化且易于序列化)

由于我们已经有了交叉链接和定义的描述符,人们会认为有一种简单的方法可以从那些已经定义的消息中构建“新”消息。到目前为止,解决方案已经暗示了我们。我们已经尝试创建自己的 DescriptorProto 并从我们已经定义的描述符中添加新的类型字段,但是迷路了(还没有深入研究这个)。我们还研究了可能将它们添加为扩展(目前未知如何这样做)。我们是否需要创建自己的DescriptorDatabase(目前也不知道怎么做)?

有什么见解吗?


BitBucket 上的链接示例源


希望这个解释会有所帮助。

我正在尝试从一组已定义的消息中动态构建消息。已经定义的消息集是通过使用官方 c++ protobuf 教程中解释(简要)的“自我描述”方法创建的(即这些消息以编译形式不可用)。这个新定义的消息需要在运行时创建。

已尝试对每条消息使用直接描述符并尝试构建 FileDescriptorProto。尝试查看 DatabaseDescriptor 方法。两者都没有运气。当前尝试将这些定义的消息作为扩展添加到另一条消息(即使在编译时这些定义的消息,并且它们的“描述符集”未被归类为扩展任何内容),这是示例代码开始的地方。

4

3 回答 3

6

你需要一个protobuf::DynamicMessageFactory

{
  using namespace google;

  protobuf::DynamicMessageFactory dmf;
  protobuf::Message* actual_msg = dmf.GetPrototype(some_desc)->New();

  const protobuf::Reflection* refl = actual_msg->GetReflection();

  const protobuf::FieldDescriptor* fd = trip_desc->FindFieldByName("someField");
  refl->SetString(actual_msg, fd, "whee");

  ... 

  cout << actual_msg->DebugString() << endl;
}
于 2014-04-17T01:17:54.940 回答
5

I was able to solve this problem by dynamically creating a .proto file and loading it with an Importer.

The only requirement is for each client to either send across its proto file (only needed at init... not during full execution). The server then saves each proto file to a temp directory. An alternative if possible is to just point the server to a central location that holds all of the needed proto files.

This was done by first using a DiskSourceTree to map actual path locations to in program virtual ones. Then building the .proto file to import every proto file that was sent across AND define an optional field in a 'master message'.

After the master.proto has been saved to disk, i Import it with the Importer. Now using the Importers DescriptorPool and a DynamicMessageFactory, I'm able to reliably generate the whole message under one message. I will be putting an example of what I am describing up later on tonight or tomorrow.

If anyone has any suggestions on how to make this process better or how to do it different, please say so.

I will be leaving this question unanswered up until the bounty is about to expire just in case someone else has a better solution.

于 2012-08-22T18:09:41.820 回答
1

如何将所有消息序列化为字符串,并使主消息成为(字节)字符串序列,a la

message MessageSet
{
  required FileDescriptorSet proto_files = 1;
  repeated bytes serialized_sub_message = 2;
}
于 2012-08-22T14:16:38.880 回答