используя отражение protobuf для получения дескриптора логического поля в переполнении стека

Я использую grpc в приложении C ++. На стороне клиента мне нужно рефлексивно запросить логическое значение из сообщения, используя отражение.

Ответное сообщение показано ниже. К сожалению, я не вижу дескрипторы полей для поля 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"

Также обратите внимание, что логическое поле в вопросе «карта» задается сервером. Глядя на сгенерированный 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)
}

2

Решение

Reflection::ListFields() только перечисляет поля, которые в настоящее время установлены. Чтобы перебрать все поля или выполнить поиск определенного поля, используйте методы доступа к полю в Descriptor, Вы можете получить дескриптор сообщения из сообщения (или из Reflection объект) с помощью GetDescriptor,

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]