使用protobuf反射在c ++中获取布尔字段描述符

时间:2016-04-18 01:07:58

标签: c++ reflection protocol-buffers descriptor

我在C ++应用程序中使用grpc。在客户端,我需要反射性地使用反射从消息中查询布尔值。

响应消息如下所示。不幸的是我看不到bool mAP字段的字段描述符 - 但是我可以看到FieldDescriptors的字符串字段,我做错了什么?

约翰

message Response {
    // OTP Connection Status
    enum OTPConnStatus {
        Disconnected              = 0;
        Connected                 = 1;
        InvalidCS                 = 2;
        DiscRequest               = 3;
    }

    // define the fields
    RXMessageType mMessageType    = 1;
    bool mAP                      = 2;
    OTPConnStatus mCS1            = 3;
    OTPConnStatus mCS2            = 4;
    OTPConnStatus mCS3            = 5;
    OTPConnStatus mCS4            = 6;
    string mOTP1                  = 7;
    string mOTP2                  = 8;
    string mOTP3                  = 9;
    string mOTP4                  = 10;
}
const auto reflection = pMessage->GetReflection();
std::vector<const FieldDescriptor*> fields;
pMessage->GetReflection()->ListFields(*pMessage, &fields);
const auto fieldIter = std::find_if(fields.cbegin(), fields.cend(),
    [&lcFieldName](const FieldDescriptor* next) {
        return boost::iequals(next->name(), lcFieldName);
    });
if (fieldIter != fields.cend()) {
    std::string result;
    auto fieldDescriptor = *fieldIter;
    if (!fieldDescriptor->is_repeated()) {
        switch (fieldDescriptor->cpp_type()) {
        case FieldDescriptor::CPPTYPE_INT32:
            result = std::to_string(reflection->GetInt32 (
                *pMessage, fieldDescriptor));
            break;
        case FieldDescriptor::CPPTYPE_INT64:
            result = std::to_string(reflection->GetInt64 (
                *pMessage, fieldDescriptor));
            break;
        case FieldDescriptor::CPPTYPE_UINT32:
            result = std::to_string(reflection->GetUInt32 (
                *pMessage, fieldDescriptor));
            break;
        case FieldDescriptor::CPPTYPE_UINT64:
            result = std::to_string(reflection->GetUInt64 (
                *pMessage, fieldDescriptor));
            break;
        case FieldDescriptor::CPPTYPE_DOUBLE:
            result = std::to_string(reflection->GetDouble (
                *pMessage, fieldDescriptor));
            break;
        case FieldDescriptor::CPPTYPE_FLOAT:
            result = std::to_string(reflection->GetFloat (
                *pMessage, fieldDescriptor));
            break;
        case FieldDescriptor::CPPTYPE_BOOL:
            result = reflection->GetBool(
                *pMessage, fieldDescriptor) ?
                "true" : "false";
            break;
        case FieldDescriptor::CPPTYPE_ENUM:
            result = reflection->GetEnum(
                *pMessage, fieldDescriptor)->
                    full_name();
            break;
        case FieldDescriptor::CPPTYPE_STRING:
            result = reflection->GetString(
                *pMessage, fieldDescriptor);
            break;
        case FieldDescriptor::CPPTYPE_MESSAGE:
            //result = reflection->GetMessage(
            //    *pMessage, fieldDescriptor);
            break;
        }
    }
    std::cout << result << std::endl;
    exit(0);
} else {
编辑:我在protobuf中发现了一个用于打印消息的实用程序,用于打印内容。结果如下:

const auto reflection = pMessage->GetReflection();
std::string formatted;
pb::TextFormat::PrintToString(*pMessage, &formatted);
std::cout << formatted;

印刷:

mMessageType: OneTimePassword
mOTP1: "TAILNO1"
mOTP2: "TAILNO2"
mOTP3: "TAILNO3"
mOTP4: "TAILNO4"

另请注意,问题“map”中的布尔字段由服务器设置。查看生成的CAService.pb.h代码并将MessageType(确实具有工作字段描述符)与mAP字段进行比较,这对于protobuf用户显示错误可能很有用在我的方法。

// optional .ca.RXMessageType mMessageType = 1;
inline void OTPResponse::clear_mmessagetype() {
  mmessagetype_ = 0;
}
inline ::ca::RXMessageType OTPResponse::mmessagetype() const {
  // @@protoc_insertion_point(field_get:ca.OTPResponse.mMessageType)
  return static_cast< ::ca::RXMessageType >(mmessagetype_);
}
inline void OTPResponse::set_mmessagetype(::ca::RXMessageType value) {

  mmessagetype_ = value;
  // @@protoc_insertion_point(field_set:ca.OTPResponse.mMessageType)
}

// optional bool mAP = 2;
inline void OTPResponse::clear_map() {
  map_ = false;
}
inline bool OTPResponse::map() const {
  // @@protoc_insertion_point(field_get:ca.OTPResponse.mAP)
  return map_;
}
inline void OTPResponse::set_map(bool value) {

  map_ = value;
  // @@protoc_insertion_point(field_set:ca.OTPResponse.mAP)
}

1 个答案:

答案 0 :(得分:3)

Reflection::ListFields()仅列出当前设置的字段。要迭代所有字段或搜索特定字段,请使用Descriptor中的字段访问方法。您可以使用Reflection从消息(或GetDescriptor对象)中获取消息描述符。