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

using protobuf reflection to get a boolean field descriptor in c++

我在 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)
}

Reflection::ListFields() 只列出当前设置的字段。要迭代所有字段或搜索特定字段,请使用 Descriptor 中的字段访问方法。您可以使用 GetDescriptor.

从消息(或从 Reflection 对象)获取消息描述符