【问题标题】:How to parse a message into the DynamicMessage class and then do the iteration through the fields?如何将消息解析为 DynamicMessage 类,然后通过字段进行迭代?
【发布时间】:2012-07-19 09:52:28
【问题描述】:

这是我想要弄清楚的,他们的文档解释得不够好,至少对我来说是这样。

塞纳里奥:

我有 5 个使用 protoc for C++ 生成的 proto 文件。我的应用程序需要接收一条消息,然后能够遍历所有字段,同时访问它们的值和名称。

我想做的是将消息解析到 DynamicMessage 类中,然后通过字段进行迭代。这样我就不必确切知道它是什么消息,我可以用一种通用的方式处理它们。

我知道可以通过将消息解析为特定类型然后将它们视为消息基类来处理消息,但对于我的应用程序来说这是不可取的。

看起来我想做的事情应该可以通过“--descriptor_set_out”和动态消息类来实现。

我尝试了什么(失败了):

我将descriptor.proto 与我的protos 一起移动到文件夹中,并将其与我的其他人一起包含在编译步骤中。我还设置了 --descriptor_set_out 标志以打印到文件“my_descriptors.pb.ds”

我不知道从那里开始。

Here's what i've referenced, although there isn't much... 很抱歉这篇文章很长,而且主题命名模式有些模糊。

另外,如果不清楚,我假设这些消息不是“未知”。我认为仍然需要为每个原型包含相应的标头,以便我的代码知道它处理的“未知”消息。

【问题讨论】:

  • 一个问题 - 你为什么要这样做?如果您将消息描述(名称和类型 - 需要能够遍历字段名称)与消息本身一起传输,那么您基本上取消了非自我描述的性能和大小奖励消息(protobuf 是)。你可以只使用 JSON。
  • @DarkWander,我的用法是为了提高效率,我有一个二进制消息,它流经一些 pub 子进程。我有另一个进程,我想坐下来收听流经 pub 子进程的所有消息。它可以包含解码消息所需的所有标头,然后我想将它们以可读的 KeyValue 字符串输出到日志文件中以用于审计/调试目的。我不想为我添加的每个新消息类型编写解码器/翻译器。只想将字节转储到正确的类型并一般地迭代字段。

标签: c++ protocol-buffers


【解决方案1】:

最常见的方式是使用消息组合。比如:

message Foo {...}
message Bar {...}
message GenericMessage {
    enum Type {FOO = 1, BAR = 2};
    optional Foo foo = 1;
    optional Bar bar = 2;
}

如果您确保每个GenericMessage 中都存在FooBar 中的一个,您将获得所需的行为。您阅读了一封GenericMessage,然后将其作为几条特定消息之一进行处理。

考虑重构协议。如果您需要做的只是遍历字段,也许您最好使用简单的键值映射:

message ValueMessage {
    required string key = 1;
    optional int IntValue = 2;
    optional string StringValue = 3;
    optional bool BoolValue = 4;
    ...
}
message GenericMessage{
    repeated ValueMessage = 1;
}

或者你可以用其他方式重构你的协议。

【讨论】:

    【解决方案2】:

    警告:我的回答并不完全正确我有一些关于冲突的编译错误,我会在修复它时进行编辑:)。但这是一个起点

    自发布此问题以来可能已经有很长时间了,但现在我在使用 Protocol Buffers 时遇到了类似的问题。

    首先引用错误,必须添加的命令选项是:

    --descriptor_set_out=<Directory>

    Directory 是您的 descriptor.proto 的编译版本(或描述您的文件的 .proto 编译版本)所在的位置。

    在此之后,您必须在自动描述的 .proto 文件中添加对 Descriptor.proto 文件的引用。

    message MyMessage
    {
        required google.protobuf.FileDescriptorSet proto_files = 1;
        ...
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-08
    • 2017-03-18
    相关资源
    最近更新 更多