protobuf C++ 利用反射获取消息内容

本文详细介绍了protobuf的反射使用,通过`google::protobuf::Message`的`GetDescriptor()`和`GetReflection()`方法获取消息字段信息。示例代码展示了如何遍历并打印protobuf消息的所有字段,包括不同类型如整型、浮点型、字符串等,并递归处理嵌套消息。注意不同protobuf版本可能存在的字段类型差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
        }
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值