protobuf经常会被大家使用,下面演示一下protobuf反射的使用。
protobuf的消息都继承了 google::protobuf::Message 这个父类。
然后可以通过这两个函数来获取消息字段的相关信息,可以看注释
下面演示一下,打印一个消息的全部字段信息。当然你可以利用这个来进行更加贴合自己需求的工作。
对了注意一下:不同版本的protobuf字段类型可能会有差异,大家可以自己比对源码的类型,有些类型可能是废弃的。
void PrintProtoMsg(const google::protobuf::Message& message)
{
const google::protobuf::Descriptor *des = message.GetDescriptor();
const google::protobuf::Reflection *ref = message.GetReflection();
int fieldCount = des->field_count();
for (int i = 0; i < fieldCount; i++)
{
///< get field with index i
const google::protobuf::FieldDescriptor *field = des->field(i);
switch (field->type())
{
case google::protobuf::FieldDescriptor::Type::TYPE_INT32:
case google::protobuf::FieldDescriptor::Type::TYPE_SINT32:
case google::protobuf::FieldDescriptor::Type::TYPE_SFIXED32:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
int32_t data = ref->GetRepeatedInt32(message, field, j);
std::cout << data << "," ;
}
}
else
{
int32_t data = ref->GetInt32(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_INT64:
case google::protobuf::FieldDescriptor::Type::TYPE_SINT64:
case google::protobuf::FieldDescriptor::Type::TYPE_SFIXED64:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
int64_t data = ref->GetRepeatedInt64(message, field, j);
std::cout << data << "," ;
}
}
else
{
int64_t data = ref->GetInt64(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_UINT32:
case google::protobuf::FieldDescriptor::Type::TYPE_FIXED32:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
uint32_t data = ref->GetRepeatedUInt32(message, field, j);
std::cout << data << "," ;
}
}
else
{
uint32_t data = ref->GetUInt32(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_UINT64:
case google::protobuf::FieldDescriptor::Type::TYPE_FIXED64:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
uint32_t data = ref->GetRepeatedUInt64(message, field, j);
std::cout << data << "," ;
}
}
else
{
uint32_t data = ref->GetUInt64(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_DOUBLE:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
double data = ref->GetRepeatedDouble(message, field, j);
std::cout << data << "," ;
}
}
else
{
double data = ref->GetDouble(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_FLOAT:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
float data = ref->GetRepeatedFloat(message, field, j);
std::cout << data << "," ;
}
}
else
{
float data = ref->GetFloat(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_BOOL:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
bool data = ref->GetRepeatedBool(message, field, j);
std::cout << data << "," ;
}
}
else
{
bool data = ref->GetBool(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_ENUM:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
const google::protobuf::EnumValueDescriptor *data = ref->GetRepeatedEnum(message, field, j);
std::cout << data << "," ;
}
}
else
{
const google::protobuf::EnumValueDescriptor *data = ref->GetEnum(message, field);
std::cout << data->number() << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_STRING:
case google::protobuf::FieldDescriptor::Type::TYPE_BYTES:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
std::cout << data << "," ;
}
}
else
{
std::string data = ref->GetString(message, field);
std::cout << data << "," ;
}
}
break;
case google::protobuf::FieldDescriptor::Type::TYPE_MESSAGE:
{
if (field->is_repeated())
{
int count = ref->FieldSize(message, field);
for (int j = 0; j < count; j++)
{
const google::protobuf::Message &innerMsg = ref->GetRepeatedMessage(message, field, j);
PrintProtoMsg(innerMsg);
}
}
else
{
const google::protobuf::Message &innerMsg = ref->GetMessage(message, field);
PrintProtoMsg(innerMsg);
}
}
break;
default:
break;
}
}
}