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定义注释的唯一方法是使用
    proto
    应用程序创建.desc文件
  • 要获取注释,只有当“top”元素是
    FileDescriptorSet
    FileDescriptorProto
    FileDesriptor
    时,才能使用GetSourceLocation成员函数。如果这是正确的,则协议缓冲区的API设计很差,因为
    google::protobuf::Message
    类是一个God类(提供对完整文件描述符API的访问,但根本不提供值)
  • 调用
    concrete\u message.descriptor()->file()
    不包含源注释信息,因为它不是编译代码的一部分 在我看来,实现这一目标的唯一途径是:

  • 使用以下参数调用message.proto文件(该文件引用所有其他消息)的proto:

    --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就包含源信息的方法吗
  • 是否可以使用具体的消息类/实例“连接”/设置
    FileDescriptorSet
    ,因为这将大大简化工作
  • 编辑2015-09-25:上帝类我的意思是
    消息类和/或描述符类提供了或多或少无用的公共功能,因为它们在客户端使用时不提供任何信息。以“正常”消息为例:因此生成的代码不包含源注释信息,因此所有描述符类(例如
    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