Protobuf 一次解析一个消息字段

问题描述 投票:0回答:1

我熟悉 protobuf 线路格式,其中设计者选择不包括线路上序列化消息的大小。

我也熟悉了从头开始应对的策略:

但是,我的看法略有不同(和问题)。

鉴于我无法控制的已经序列化的消息,我想一次加载它的每个字段。请注意,虽然序列化消息的大小未编码(请参阅前面的项目符号),但其每个字段的大小编码的。此外,field id也被编码。请参阅此处

所以从理论上讲,应该有可能有像下面的函数

ParseMsgField
这样的东西。如果给定一个先前序列化的 Root 对象(因此,它的字段确实被编码),则一次加载它的每个字段。

package my_proto;

message SubType0 {
    uint32 Val = 1;
}

message SubType1 {
    uint32 Val = 1;
}

message Root {
    repeated SubType0 subtype = 1;
    repeated SubType1 subtype = 2;
}
#include "my_proto.pb.h"

// how to implement this...?
int ParseMsgField(Descriptor* root_descriptor, Message* field_msg);

int main() {
    auto* root_descriptor = my_proto::Root::descriptor();

    google::protobuf::Message* field_msg;
    while(true) {
        int field_id = ParseMsgField(root_descriptor, field_msg);
        if (field_id == -1) {
            break;
        }

        // handle each field type, either dynamic_cast or test field_id + static_cast
    }

我想知道如何实现

ParseMsgField
功能?我使用的输入参数是猜测我可能需要什么...

我想如果这是可能的,一个限制是 Root 的所有子类型都必须是消息类型才能工作?

c++ protocol-buffers
1个回答
0
投票

要一次解析一个 Protobuf 消息字段,可以使用 Protobuf 库中的

ParseFromArray
ParseFromIstream
方法。这是一个简短的指南:

  1. 使用

    ParseFromArray

    MyMessage msg;
    // Assuming 'data' is a byte array containing your Protobuf message
    if (msg.ParseFromArray(data, size)) {
        // Successfully parsed the entire message
        // Access fields as needed
        int field_value = msg.field_name();
    } else {
        // Handle parse error
    }
    
  2. 使用

    ParseFromIstream

    MyMessage msg;
    std::ifstream input_file("message.bin", std::ios::binary);
    if (msg.ParseFromIstream(&input_file)) {
        // Successfully parsed the message
        // Access fields as needed
        int field_value = msg.field_name();
    } else {
        // Handle parse error
    }
    

要单独处理字段,您可以在解析后检查每个字段的存在和值。为了进行详细控制,如果 Protobuf 库支持此类操作,您可能需要迭代字段。

如果您需要更多具体细节或有任何其他问题,请告诉我! 访问:https://topfollow-apk.com/blog/

© www.soinside.com 2019 - 2024. All rights reserved.