【问题标题】:How can I add my own code to JAVA generated classes from proto file?如何将我自己的代码从 proto 文件添加到 JAVA 生成的类中?
【发布时间】:2018-11-21 05:52:47
【问题描述】:

我正在使用 protobuf,并且正在从以下 proto 文件生成 JAVA 类。

syntax = "proto3";
enum Greeting {
    NONE = 0;
    MR = 1;
    MRS = 2;
    MISS = 3;
}

message Hello {
    Greeting greeting = 1;
    string name = 2;
}

message Bye {
    string name = 1;
}

option java_multiple_files = true;

现在我需要向生成的文件添加一些代码,我发现可以使用自定义插件 (https://developers.google.com/protocol-buffers/docs/reference/java-generated#plugins)。我正在尝试用 Java 生成该插件,类似这样。

public class Test {
   PluginProtos.CodeGeneratorResponse.getDefaultInstance();
   /* Code to get generated files from java_out and use the insertion points */
   codeGeneratorResponse.writeTo(System.out);
}

然后我运行

protoc --java_out=./classes --plugin=protoc-gen-demo=my-plugin --demo_out=. example.proto

问题是在我的Test.java 主要方法中,我不知道如何访问由选项--java_out 创建的文件,以便我可以使用它们的插入点。目前,默认实例的 CodeGeneratorResponse 为空(无文件)。

有人知道我如何从 --java_out 获取CodeGeneratorResponse 以便我可以向生成的类添加更多代码吗?

提前致谢。

【问题讨论】:

  • 你有没有想过这个问题?或者你有你工作的例子吗?

标签: protocol-buffers protoc protobuf-java


【解决方案1】:

我最近也遇到了这个问题,无法找到一个好的答案。盯着CodeGeneratorResponse消息中的cmets看了一会儿,终于明白了。

起初让我失望的是,我将插件视为管道,其中一个的输出馈送到下一个。然而,每个插件都获得完全相同的输入(通过CodeGeneratorRequest 消息表示的已解析的 .proto 文件),并且所有从插件生成的代码(包括内置代码)都被合并到输出文件。但是,插件可能会修改以前插件的输出,这就是插入点的设计目的。

具体到您的问题,您将在响应中添加一个file,并将name 字段设置为生成的Java 文件的名称,insertion_point 字段设置为插入点的名称您要添加代码,然后将 content 字段设置为您要在该点插入的代码。

我发现this article 有助于创建一个简单的插件(在本例中为 python)。作为一个简单的测试,我修改了那篇文章中的generate_code 函数,如下所示:

def generate_code(request, response):
    for proto_file in request.proto_file:
        f = response.file.add()
        f.name = "Test.java"
        f.insertion_point = "outer_class_scope"
        f.content = "// Inserting a comment as a test"

然后我用插件运行 protoc:

$ cat test.proto
syntax = "proto3";
message MyMsg {
    int32 num = 1;
}
$ protoc --plugin=protoc-gen-sample=sample_proto_gen.py --java_out=. --sample_out=. test.proto
$ tail -n3 Test.java
  // Inserting a comment as a test
  // @@protoc_insertion_point(outer_class_scope)
}

您的插件只需要是一些可执行文件,它从标准输入读取CodeGeneratorRequest 消息并将CodeGeneratorResponse 消息写入标准输出,因此当然可以用Java 编写。我只是选择了 python,因为我通常更喜欢它,并找到了这个简单的例子。

作为参考,here's a plugin 我为基于自定义 protobuf 选项生成代码而编写。

【讨论】:

  • 哇。这是很难找到的信息。我认为插件链也可以作为管道工作。谢谢!
【解决方案2】:

我制作了一个自定义 python 插件。 要运行我的插件,我使用以下命令:

protoc --plugin=protoc-gen-custom=my_plugin_executable_file --custom_out=./build test.proto

所以我认为,你必须从你的 .java 文件生成一个可执行文件并在你的命令中使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 2016-05-21
    相关资源
    最近更新 更多