Чтение комментариев из файлов .proto с использованием объекта дескриптора Protocol Buffers

Я в настоящее время пересматриваю проект с помощью Google Буферы протокола.

В проекте я хочу использовать возможности Дескрипторы а также отражение буферов протокола.

Официальная документация гласит, что комментарии .proto файлы можно прочитать:

  1. С функцией DebugStringWithOptions(), вызывается на сообщение или дескриптор.
  2. С функцией GetSourceLocation(), вызвал дескриптор.

Я не могу получить комментарии, поэтому я думаю, что делаю что-то не так или эта функция еще не полностью реализована в буферах протокола.

Вот некоторые фрагменты кода:

google::protobuf::DebugStringOptions options;
options.include_comments = true;
std::cout << "google::protobuf::Descriptor::DebugStringWithOptions(): "<< message.descriptor()->DebugStringWithOptions(options) << std::endl
<< std::endl;

const google::protobuf::FieldDescriptor* field_descriptor{
message.descriptor()->field(1)};

// TODO(wolters): Why doesn't this work?
google::protobuf::SourceLocation* source_location{
new google::protobuf::SourceLocation};
field_descriptor->GetSourceLocation(source_location);

// if (field_descriptor->GetSourceLocation(source_location)) {
std::cout << "start_line: " << source_location->leading_comments
<< std::endl;
std::cout << "end_line: " << source_location->leading_comments << std::endl;
std::cout << "start_column: " << source_location->start_column << std::endl;
std::cout << "end_column: " << source_location->end_column << std::endl;
std::cout << "leading_comments: " << source_location->leading_comments
<< std::endl;
std::cout << "trailing_comments: " << source_location->trailing_comments
<< std::endl;
// }

Я попытался использовать следующие два синтаксиса для комментариев в .proto файл,
но ни один из них не работает

MessageHeader header = 1;  // The header of this `Message`.

/**
* The header of this `Message`.
*/
MessageHeader header = 1;

Я использую GCC 4.7.1 (с включенной поддержкой C ++ 11) и последнюю версию Protocol Buffers версии 3.0.0-alpha-4.1.

Может ли кто-нибудь направить меня в правильном направлении и / или привести мне рабочий пример?

РЕДАКТИРОВАТЬ 2015-09-24:

После рассмотрения Сообщения с самоописанием В разделе официальной документации и тестирования многих вещей, мне кажется, я немного лучше понимаю дескрипторы protobuf.

Поправьте меня, если одно или несколько из следующих утверждений неверны:

  1. SelfDescribingMessage прото только полезно, если другой конец не знает определения .proto.
  2. Единственный способ получить доступ к комментариям прототипа — создать файл .desc с помощью protoc приложение.
  3. Чтобы получить комментарий, функцию-член GetSourceLocation можно использовать только в том случае, если верхний элемент FileDescriptorSet, FileDescriptorProto или же FileDesriptor, Если это правильно, у протокола Buffers плохой дизайн API, так как google::protobuf::Message class является классом God (обеспечивает доступ к полному API дескриптора файла, но значения не предоставляются вообще).
  4. Вызов concrete_message.descriptor()->file() не (а также не может) содержать информацию об исходных комментариях, поскольку она не является частью скомпилированного кода.

Мне кажется, что единственный способ сделать эту работу:

  1. Вызвать protoc для файла Message.proto (который ссылается на все остальные сообщения) с аргументами:

    --include_imports --include_source_info and --descriptor_set_out=message.desc
    
  2. Корабль message.desc файл вместе с приложением / библиотекой, чтобы иметь возможность читать его во время выполнения (см. ниже).

  3. Создать google::protobuf::FileDescriptorSet из этого файла.
  4. Перебрать все google::protobuf::FileDescriptorProto из FileDescriptorSet,
  5. Конвертировать каждый FileDescriptorProto в google::protobuf::FileDescriptor с помощью google::protobuf::DescriptorPool::BuildFile(),
  6. Поиск сообщения и / или полей с одним из Find… функции, применяемые на FileDescriptor пример.
  7. Вызвать функцию GetSourceLocation на экземпляре дескриптора сообщения / поля.
  8. Прочитайте комментарии через google::protobuf::SourceLocation::leading_comments а также google::protobuf::SourceLocation::trailing_comments,

Это кажется мне довольно сложным, поэтому у меня есть два дополнительных вопроса:

  1. Разве нет способа включить информацию об источнике без использования FileDescriptorSet?
  2. Можно ли «подключить» / установить FileDescriptorSet с конкретным классом / экземпляром Message, так как это значительно упростит ситуацию?

РЕДАКТИРОВАТЬ 2015-09-25: От Бог класс Я имею в виду, что Message Класс и / или классы дескрипторов предлагают общедоступные функции, которые более или менее бесполезны, поскольку они не предоставляют никакой информации при использовании клиентом. Возьмите «нормальное» сообщение, например: так сгенерированный код делает не содержат информацию исходного комментария, поэтому GetSourceLocation метод во всех классах дескрипторов (например, Descriptor а также FieldDescriptor) совершенно бесполезно. С логической точки зрения отдельные случаи DescriptorLite а также FieldDescriptorLite должны быть предоставлены, если речь идет о сообщениях и Descriptor а также FieldDescriptor если иметь дело с информацией из FileDescriptorSet (источником которого обычно является файл .desc, сгенерированный из файла .proto). [...]Lite Тогда класс будет родительским классом «нормального» класса. Аргумент, что protoc возможно, никогда не будет включать исходные комментарии, подчеркивает мою точку зрения.

Под «подключением» я подразумеваю функцию API для Обновить информация дескриптора в сообщении с информацией дескриптора из файла .desc (который всегда является расширенным набором дескрипторов, предоставленных сообщением, если я правильно понял).

2

Решение

Похоже, вы в основном поняли это.

Вы углубляетесь в API внутри компилятора протокола, которые на самом деле не были предназначены для публичного использования. Это становится сложным, потому что никто не написал вспомогательный слой для упрощения вещей, потому что не многие люди используют эти функции.

Я не уверен, что вы имеете в виду Message будучи «классом Бога». Message это просто абстрактный интерфейс для экземпляра protobuf. Дескрипторы описывают типы протобуф экземпляров. Message::getDescriptor() возвращает тип сообщения, но кроме этого между этими API-интерфейсами нет прямой связи …

Разве нет способа включить информацию об источнике без использования FileDescriptorSet?

Комментарии намеренно удаляются из дескрипторов, встроенных в сгенерированный код, поэтому вам нужно запустить парсер отдельно, сгенерировать набор дескрипторов и использовать его динамически.

Можно ли «соединить» / установить FileDescriptorSet с конкретным классом / экземпляром Message, поскольку это значительно упростит ситуацию?

Вы хотите сказать, что вы хотите, чтобы Message :: getDescriptor () возвращал дескриптор, включающий данные комментариев из исходного файла? Это потребует, чтобы данные комментариев были встроены в сгенерированный код, что было бы тривиально для protoc реализовать (в настоящее время он намеренно удаляет их, так что просто нужно не сделать это), но потенциально вздорными и опасными (может раскрыть секреты для людей, отправляющих двоичные файлы с закрытым исходным кодом, созданные с помощью protobufs).

1

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

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

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