Я в настоящее время пересматриваю проект с помощью Google Буферы протокола.
В проекте я хочу использовать возможности Дескрипторы а также отражение буферов протокола.
Официальная документация гласит, что комментарии .proto
файлы можно прочитать:
DebugStringWithOptions()
, вызывается на сообщение или дескриптор.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.
Поправьте меня, если одно или несколько из следующих утверждений неверны:
SelfDescribingMessage
прото только полезно, если другой конец не знает определения .proto.protoc
приложение.FileDescriptorSet
, FileDescriptorProto
или же FileDesriptor
, Если это правильно, у протокола Buffers плохой дизайн API, так как google::protobuf::Message
class является классом God (обеспечивает доступ к полному API дескриптора файла, но значения не предоставляются вообще).concrete_message.descriptor()->file()
не (а также не может) содержать информацию об исходных комментариях, поскольку она не является частью скомпилированного кода. Мне кажется, что единственный способ сделать эту работу:
Вызвать protoc для файла Message.proto (который ссылается на все остальные сообщения) с аргументами:
--include_imports --include_source_info and --descriptor_set_out=message.desc
Корабль message.desc
файл вместе с приложением / библиотекой, чтобы иметь возможность читать его во время выполнения (см. ниже).
google::protobuf::FileDescriptorSet
из этого файла.google::protobuf::FileDescriptorProto
из FileDescriptorSet
,google::protobuf::FileDescriptor
с помощью google::protobuf::DescriptorPool::BuildFile()
,Find…
функции, применяемые на FileDescriptor
пример.GetSourceLocation
на экземпляре дескриптора сообщения / поля.google::protobuf::SourceLocation::leading_comments
а также google::protobuf::SourceLocation::trailing_comments
,Это кажется мне довольно сложным, поэтому у меня есть два дополнительных вопроса:
FileDescriptorSet
с конкретным классом / экземпляром Message, так как это значительно упростит ситуацию?РЕДАКТИРОВАТЬ 2015-09-25: От Бог класс Я имею в виду, что Message
Класс и / или классы дескрипторов предлагают общедоступные функции, которые более или менее бесполезны, поскольку они не предоставляют никакой информации при использовании клиентом. Возьмите «нормальное» сообщение, например: так сгенерированный код делает не содержат информацию исходного комментария, поэтому GetSourceLocation
метод во всех классах дескрипторов (например, Descriptor
а также FieldDescriptor
) совершенно бесполезно. С логической точки зрения отдельные случаи DescriptorLite
а также FieldDescriptorLite
должны быть предоставлены, если речь идет о сообщениях и Descriptor
а также FieldDescriptor
если иметь дело с информацией из FileDescriptorSet
(источником которого обычно является файл .desc, сгенерированный из файла .proto). [...]Lite
Тогда класс будет родительским классом «нормального» класса. Аргумент, что protoc
возможно, никогда не будет включать исходные комментарии, подчеркивает мою точку зрения.
Под «подключением» я подразумеваю функцию API для Обновить информация дескриптора в сообщении с информацией дескриптора из файла .desc (который всегда является расширенным набором дескрипторов, предоставленных сообщением, если я правильно понял).
Похоже, вы в основном поняли это.
Вы углубляетесь в API внутри компилятора протокола, которые на самом деле не были предназначены для публичного использования. Это становится сложным, потому что никто не написал вспомогательный слой для упрощения вещей, потому что не многие люди используют эти функции.
Я не уверен, что вы имеете в виду Message
будучи «классом Бога». Message
это просто абстрактный интерфейс для экземпляра protobuf. Дескрипторы описывают типы протобуф экземпляров. Message::getDescriptor()
возвращает тип сообщения, но кроме этого между этими API-интерфейсами нет прямой связи …
Разве нет способа включить информацию об источнике без использования FileDescriptorSet?
Комментарии намеренно удаляются из дескрипторов, встроенных в сгенерированный код, поэтому вам нужно запустить парсер отдельно, сгенерировать набор дескрипторов и использовать его динамически.
Можно ли «соединить» / установить FileDescriptorSet с конкретным классом / экземпляром Message, поскольку это значительно упростит ситуацию?
Вы хотите сказать, что вы хотите, чтобы Message :: getDescriptor () возвращал дескриптор, включающий данные комментариев из исходного файла? Это потребует, чтобы данные комментариев были встроены в сгенерированный код, что было бы тривиально для protoc
реализовать (в настоящее время он намеренно удаляет их, так что просто нужно не сделать это), но потенциально вздорными и опасными (может раскрыть секреты для людей, отправляющих двоичные файлы с закрытым исходным кодом, созданные с помощью protobufs).
Других решений пока нет …