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

joh*_*co3 2 c++ reflection descriptor protocol-buffers

I am using grpc in a C++ application. On the client side, I need to reflectively query a boolean value from a message using reflection.

响应消息如下所示。不幸的是,我看不到 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;
}
Run Code Online (Sandbox Code Playgroud)
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 {
Run Code Online (Sandbox Code Playgroud)

编辑:我在 protobuf 中找到了一个实用程序,用于打印我用来打印内容的消息。结果如下:

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

打印:

mMessageType: OneTimePassword
mOTP1: "TAILNO1"
mOTP2: "TAILNO2"
mOTP3: "TAILNO3"
mOTP4: "TAILNO4"
Run Code Online (Sandbox Code Playgroud)

另请注意,有问题的 '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)
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*ein 5

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