使用Protocol Buffers描述符对象从.proto文件读取注释 [英] Reading comments from .proto files using a Protocol Buffers descriptor object

查看:2519
本文介绍了使用Protocol Buffers描述符对象从.proto文件读取注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用Google 协议缓冲区重新访问一个项目。

I am currently revisiting a project using Google Protocol Buffers.

在项目中,我想要使用Protocol Buffers的 Descriptors 反射

In the project I want to make use of the features Descriptors and Reflection of Protocol Buffers.

官方文档声明 .proto 文件的注释可以读取:

The official documentation states that the comments of .proto files can be read:


  1. 使用函数 DebugStringWithOptions() ,对消息或描述符调用。

  2. 使用函数 GetSourceLocation() ,调用描述符。

  1. With the function DebugStringWithOptions(), called on a message or descriptor.
  2. With the function GetSourceLocation(), called on a descriptor.

我无法检索注释,所以我认为我做的完全错误,

I am unable to retrieve comments, so I think I am doing something completely wrong or that feature isn't fully implemented in Protocol Buffers, yet.

以下是一些代码片段:

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 文件,
,但它们都不起作用:

I've tried using the following two syntaxes for comments in the .proto file, but none of them seems to work:

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

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



我使用GCC 4.7.1(启用C ++ 11支持)和最新的协议缓冲区版本3.0.0-alpha-4.1。

I am using GCC 4.7.1 (with C++11 support enabled) and the latest Protocol Buffers version 3.0.0-alpha-4.1.

有人可以指导我走向正确的方向和/或提供一个工作实例吗?

Can someone guide me into the correct direction and/or provide me an working example?

EDIT 2015-09-24:

在支付自我描述消息部分的官方文档和测试很多东西,在我看来,我有一个更好的理解

After rearding the Self Describing Messages section in the official documentation and testing lots of stuff, it seems to me that I have a bit better understanding of protobuf descriptors.

如果以下一个或多个语句不正确,请更正我:

Correct me if one or more of the following statements are incorrect:


  1. 如果对方不知道.proto定义, SelfDescribingMessage proto只有有用。

  2. 访问proto定义的注释的唯一方法是使用 protoc 应用程序创建.desc文件。

  3. 要获取注释,GetSourceLocation成员函数只能在top元素为 FileDescriptorSet FileDescriptorProto FileDesriptor 。如果这是正确的,Protocol Buffers有一个糟糕的API设计,因为 google :: protobuf :: Message 类是一个神类(提供访问完整的文件描述符API, ctrl_message.descriptor() - > file()不会(不会提供值)。

  4. < 不能包含源评论信息,因为它不是编译代码的一部分。
  1. The SelfDescribingMessage proto is only useful if the other end does not know the .proto definitions.
  2. The only way to access the comments of the proto definition is by creating a .desc file using the protoc application.
  3. To obtain a comment, the GetSourceLocation member function can only be used if the "top" element is either FileDescriptorSet, FileDescriptorProto or FileDesriptor. If this is correct, Protocol Buffers has a poor API design, since the google::protobuf::Message class is a God Class (providing access to the complete file descriptor API, but the values are not provided at all).
  4. The call concrete_message.descriptor()->file() does not (and can not) contain source comments information, since it is not part of the compiled code.

在我看来,这项工作的唯一方法是:

It seems to me that the only way to make this work is:


  1. 使用参数调用theMessage.proto文件(引用所有其他消息)的原型:

  1. Invoke protoc for theMessage.proto file (which references all other messages) with the arguments:

--include_imports --include_source_info and --descriptor_set_out=message.desc


  • message.desc 文件与应用程序/库一起运送,以便在运行时读取它(见下文)。

  • Ship the message.desc file together with the application/library to be able to read it during runtime (see below).

    这看起来很复杂,所以我还有两个问题:

    This seems pretty complicated to me, so I have two additional questions:


    1. 是否可以不使用FileDescriptorSet来包含源信息?

    2. 可以连接/设置 FileDescriptorSet 与具体的Message类/实例,因为这将大大简化事情?

    1. Isn't there a way to include the source information without using a FileDescriptorSet?
    2. Is it possible to "connect"/set the FileDescriptorSet with a concrete Message class/instance, since that would drastically simplify things?

    EDIT 2015-09-25:上帝类我的意思是 Message 类和/或描述符类提供公共函数因为它们在客户端使用时不提供任何信息。以正常消息为例:所以生成的代码包含源注释信息,因此 GetSourceLocation 方法在所有描述符类中描述符 FieldDescriptor )完全无用。从逻辑角度来看,如果处理消息和描述符,应提供单独的实例 DescriptorLite FieldDescriptorLite 如果处理来自 FileDescriptorSet (其源通常为.desc)的信息,则 FieldDescriptor 从.proto文件生成的文件)。一个 [...] Lite 类将是一个普通类的父类。 protoc 可能永远不会包括来源评论,这强调了我的观点。

    EDIT 2015-09-25: By God Class I mean that the Message class and/or the descriptor classes offer public functions that are more or less useless, since they provide no information when used by a client. Take a "normal" message for example: So the generated code does not contain source comment information, therefore the GetSourceLocation method in all descriptor classes (e.g. Descriptor and FieldDescriptor) is completely useless. From a logical perspective separate instances DescriptorLite and FieldDescriptorLite should be provided if dealing with messages and Descriptor and FieldDescriptor if dealing with information from a FileDescriptorSet (whose source is normally a .desc file generated from a .proto file). A [...]Lite class would then be the parent class of a "normal" class. The argument that protoc will possibly never include source comments, underlines my point.

    一个API函数,用于使用来自.desc文件的描述符信息更新消息中的描述符信息(如果我正确理解,它始终是消息提供的描述符的超集)。

    By "connecting", I mean an API function to update the descriptor information in the message with the descriptor information from the .desc file (which is always a superset of the descriptors provided by the message, if I understood correctly).

    推荐答案

    这听起来像是你已经想出来了。

    It sounds like you've basically figured it out.

    深入到协议编译器中的API,这些API并不是为了公共消费而设计的。它变得很复杂,因为没有人写了一个辅助层来简化事情,因为没有很多人使用这些功能。

    You're getting deep into APIs inside the protocol compiler which were not really designed for public consumption. It gets complicated because no one has written a helper layer to simplify things, because not many people use these features.

    我不知道你的意思是信息是一个神类。 消息只是protobuf实例的抽象接口。描述符描述protobuf实例的类型 Message :: getDescriptor()返回消息的类型,但超出这些API之间没有太多的直接连接...

    I am not sure what you mean about Message being a "God class". Message is merely the abstract interface for a protobuf instance. Descriptors describe types of protobuf instances. Message::getDescriptor() returns the type of a message, but beyond that there isn't much direct connection between these APIs...


    有没有办法在不使用FileDescriptorSet的情况下包含源信息?

    Isn't there a way to include the source information without using a FileDescriptorSet?

    注释被有意地从嵌入到生成的代码中的描述符中去除,因此您需要单独运行解析器,生成描述符集并动态地使用它。

    The comments are intentionally stripped from the descriptors embedded into the generated code, so you need to run the parser separately, generate a descriptor set, and consume it dynamically.


    是否可以用一个具体的Message类/实例连接/设置FileDescriptorSet,因为这将大大简化事情?

    Is it possible to "connect"/set the FileDescriptorSet with a concrete Message class/instance, since that would drastically simplify things?

    你是否想让Message :: getDescriptor()返回一个包含来自源文件的注释数据的描述符?这将需要将注释数据嵌入到生成的代码中,这对于实现 protoc 是微不足道的(它目前有意地去除它们,因此它只需要不是这样做),但可能是膨胀和危险的(可以揭示为运送由protobuf构建的封闭源代码二进制文件的人的秘密)。

    Do you mean that you want Message::getDescriptor() to return a descriptor that includes the comment data from the source file? That would require that the comment data be embedded into generated code, which would be trivial for protoc to implement (it currently intentionally strips them out, so it would just have to not do that) but potentially bloat-y and dangerous (could reveal secrets for people shipping closed-source binaries built with protobufs).

    这篇关于使用Protocol Buffers描述符对象从.proto文件读取注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆