gpt4 book ai didi

c++ protobuf : how to iterate through fields of message?

转载 作者:IT老高 更新时间:2023-10-28 22:34:19 29 4
gpt4 key购买 nike

我是 protobuf 的新手,但我的任务很简单:我需要遍历消息字段并检查它的类型。如果类型是消息,我将递归地对此消息执行相同的操作。

例如,我有这样的消息:

package MyTool;

message Configuration {
required GloablSettings globalSettings = 1;
optional string option1 = 2;
optional int32 option2 = 3;
optional bool option3 = 4;

}

message GloablSettings {
required bool option1 = 1;
required bool option2 = 2;
required bool option3 = 3;
}

现在,要在 C++ 中显式访问字段值,我可以这样做:

MyTool::Configuration config;
fstream input("config", ios::in | ios::binary);
config.ParseFromIstream(&input);

bool option1val = config.globalSettings().option1();
bool option2val = config.globalSettings().option2();

等等。这种方式在字段量大的情况下不太方便。

我可以通过迭代来执行此操作并获取字段的名称和类型吗?我知道有 descriptors 类型,有点称为 reflection,但我的尝试没有成功。如果可能的话,有人可以给我一些代码示例吗?

谢谢!

最佳答案

这是旧的,但也许有人会受益。这是一个打印 protobuf 消息内容的方法:

 void Example::printMessageContents(std::shared_ptr<google::protobuf::Message> m)
{
const Descriptor *desc = m->GetDescriptor();
const Reflection *refl = m->GetReflection();
int fieldCount= desc->field_count();
fprintf(stderr, "The fullname of the message is %s \n", desc->full_name().c_str());
for(int i=0;i<fieldCount;i++)
{
const FieldDescriptor *field = desc->field(i);
fprintf(stderr, "The name of the %i th element is %s and the type is %s \n",i,field->name().c_str(),field->type_name());
}
}

您可以在 FieldDescriptor Enum Values 中找到您从 field->type 获得的可能值。例如对于消息类型,您必须检查类型是否等于 FieldDescriptor::TYPE_MESSAGE

此函数打印 protobuf 消息的所有“元数据”。但是,您需要分别检查每个值的类型,然后使用 Reflection 调用相应的 getter 函数。 .

所以使用这个条件我们可以提取字符串:

 if(field->type() == FieldDescriptor::TYPE_STRING  && !field->is_repeated())
{
std::string g= refl->GetString(*m, field);
fprintf(stderr, "The value is %s ",g.c_str());
}

但是,字段可以重复或不重复,两种字段类型使用不同的方法。所以这里使用检查来确保我们使用了正确的方法。对于重复的字段,我们有例如这种字符串方法:

GetRepeatedString(const Message & message, const FieldDescriptor * field, int index)

所以它考虑了重复字段的索引。

对于Message类型的FieldDescriptor,提供的函数只会打印消息的名称,我们最好也打印它的内容。

      if(field->type()==FieldDescriptor::TYPE_MESSAGE)
{
if(!field->is_repeated())
{
const Message &mfield = refl->GetMessage(*m, field);
Message *mcopy = mfield.New();
mcopy->CopyFrom(mfield);
void *ptr = new std::shared_ptr<Message>(mcopy);
std::shared_ptr<Message> *m =
static_cast<std::shared_ptr<Message> *>(ptr);
printMessageContents(*m);
}
}

最后,如果字段重复,您将不得不在反射上调用 FieldSize 方法并迭代所有重复的字段。

关于c++ protobuf : how to iterate through fields of message?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23963978/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com