欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Protobuf-Plugin机制

程序员文章站 2022-05-13 22:05:34
...

plugin机制

protobuf是一个支持plugin机制的序列化框架,除了protobuf自带的几种语言的CodeGenerator,用户可以按需实现自己的插件,来实现语言的拓展(比如protoc-gen-lua)或者功能的拓展(厂子内部的mcpack2pb插件)。

因为protoc插件需要实现跨平台、跨语言,所以采用的方式是父子进程的工作方式,父子进程通过pipe(父子进程共享fd)方式通信,父子进程通信数据的格式定义在compiler/plugin.proto。

  1. 父进程(protoc进程)中负责读取proto文件,转化为CodeGeneratorRequest格式,启动子进程,以及后续持久化子进程返回内容;
  2. 子进程(自定义插件进程)完成中子进程中启动自定义的CodeGeneratorResponse格式,按照自己需要完成处理,返回给父进程(protoc进程);

Protobuf-Plugin机制

父子进程共享fd工作机制说明:

利用父子进程共享fd机制,建立pipe(单工模式)。

  1. 子进程一侧,做重定向,将stdin_pipe[0]重定向到STDIN_FILENOstdout_pipe[1]重定向到STDOUT_FILENO,这样plugin处理过程中,无需记录下输入/输出fd;
  2. 父进程一侧,从stdin_pipe[1]写入数据,然后从stdout_pipe[0]读数据;

父子进程通信接口定义说明:

定义格式在compiler/plugin.proto中,也是采用proto方式来完成自定义的。

CodeGeneratorRequest按照文件粒度FileDescriptorProto来提供:

        message CodeGeneratorRequest {
          repeated string file_to_generate = 1;
          optional string parameter = 2;
          repeated FileDescriptorProto proto_file = 15;
}

CodeGeneratorResponse 返回结果中,返回文件内容是直接用string表达,protoc主进程直接负责后续持久化:

        message CodeGeneratorResponse {
          optional string error = 1;

          // Represents a single generated file.
          message File {
            optional string name = 1;
            optional string insertion_point = 2;
            optional string content = 15;
          }
          repeated File file = 15;
        }

plugin实现方式:

自定义 CodeGenerator类的子类MyCodeGenerator,在plugin进程的main函数中直接调用google::protobuf::compiler::PluginMain()

int main(int argc, char* argv[]) {
         MyCodeGenerator generator;
         return google::protobuf::compiler::PluginMain(argc, argv, &generator);
       }

google::protobuf::compiler::PluginMain()的功能:

  1. 从STDIN_FILENO读取protoc主进程的输入数据,并且反序列化到CodeGeneratorRequest request;
  2. 从FileDescriptorProto产出FileDescriptor
  3. 调用MyCodeGenerator::Generate()
  4. 输出CodeGeneratorResponse response序列化之后的结果到STDOUT_FILENO,提供给protoc主进程

Subprocess类

  1. 负责建立父子进程之间的pipe,启动子进程
  2. 完成父子进程之间通信的数据格式转换
相关标签: protobuf