C++ 使用协议缓冲区描述符对象从.proto文件读取注释
我目前正在使用谷歌重新访问一个项目 在这个项目中,我想利用特性描述符和协议缓冲区的反射 官方文件规定,C++ 使用协议缓冲区描述符对象从.proto文件读取注释,c++,c++11,protocol-buffers,descriptor,proto3,C++,C++11,Protocol Buffers,Descriptor,Proto3,我目前正在使用谷歌重新访问一个项目 在这个项目中,我想利用特性描述符和协议缓冲区的反射 官方文件规定,.proto文件的注释可以阅读: 使用函数,在消息或描述符上调用 使用函数,在描述符上调用 我无法检索注释,因此我认为我做了一些完全错误的事情,或者该功能尚未在协议缓冲区中完全实现 以下是一些代码片段: google::protobuf::DebugStringOptions options; options.include_comments = true; std::cout <<
.proto
文件的注释可以阅读:
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;
// }
我正在使用GCC4.7.1(启用了C++11支持)和最新的协议缓冲区版本3.0.0-alpha-4.1
是否有人能引导我进入正确的方向和/或为我提供一个工作示例
编辑2015-09-24:
在官方文档中重新整理了这个部分并测试了很多东西之后,我似乎对protobuf描述符有了更好的理解
如果以下一个或多个陈述不正确,请更正:
selfdescripingmessage
proto只有在另一端不知道.proto定义时才有用proto
应用程序创建.desc文件FileDescriptorSet
、FileDescriptorProto
或FileDesriptor
时,才能使用GetSourceLocation成员函数。如果这是正确的,则协议缓冲区的API设计很差,因为google::protobuf::Message
类是一个God类(提供对完整文件描述符API的访问,但根本不提供值)concrete\u message.descriptor()->file()
不包含源注释信息,因为它不是编译代码的一部分李>
在我看来,实现这一目标的唯一途径是:
--include_imports --include_source_info and --descriptor_set_out=message.desc
message.desc
文件与应用程序/库一起发送,以便能够在运行时读取该文件(见下文)google::protobuf::FileDescriptorSet
FileDescriptorSet
的google::protobuf::FileDescriptorProto
google::protobuf::DescriptorPool::BuildFile()
将每个FileDescriptorProto转换为google::protobuf::FileDescriptor
FileDescriptor
实例的Find…
函数之一查找消息和/或字段GetSourceLocation
google::protobuf::SourceLocation::leading_comments
和google::protobuf::SourceLocation::training_comments
阅读评论FileDescriptorSet
,因为这将大大简化工作消息类和/或描述符类提供了或多或少无用的公共功能,因为它们在客户端使用时不提供任何信息。以“正常”消息为例:因此生成的代码不包含源注释信息,因此所有描述符类(例如descriptor
和FieldDescriptor
)中的GetSourceLocation
方法完全无用。从逻辑角度来看,如果处理消息和描述符
以及字段描述符
则应提供单独的实例描述符
和字段描述符
如果处理文件描述符集
中的信息(其源通常是从.proto文件生成的.desc文件). 然后,[…]Lite
类将成为“普通”类的父类。protoc
可能永远不会包含源注释的论点强调了我的观点
通过“连接”,我指的是一个API函数,它用.desc文件中的描述符信息更新消息中的描述符信息(如果我理解正确,它总是消息提供的描述符的超集)。听起来您基本上已经解决了这个问题
您将深入了解协议编译器中的API,这些API并不是真正为公共消费而设计的。它变得复杂,因为没有人编写帮助层来简化事情,因为没有多少人使用这些特性
我不知道你所说的信息
是什么意思<代码>消息
只是protobuf实例的抽象接口。描述符描述protobuf实例的类型<代码>消息::getDescriptor()返回消息的类型,但除此之外,这些API之间没有太多直接的连接
难道没有一种不使用FileDescriptorSet就包含源信息的方法吗
注释是有意从嵌入生成代码的描述符中剥离出来的,因此您需要单独运行解析器,生成描述符集,并动态使用它
是否可以使用具体的消息类/实例“连接”/设置FileDescriptorSet,因为这将大大简化工作
您的意思是希望Message::getDescriptor()返回一个包含
--include_imports --include_source_info and --descriptor_set_out=message.desc