Protobuf-Plugin机制
程序员文章站
2022-05-13 22:05:34
...
plugin机制
protobuf是一个支持plugin机制的序列化框架,除了protobuf自带的几种语言的CodeGenerator,用户可以按需实现自己的插件,来实现语言的拓展(比如protoc-gen-lua)或者功能的拓展(厂子内部的mcpack2pb插件)。
因为protoc插件需要实现跨平台、跨语言,所以采用的方式是父子进程的工作方式,父子进程通过pipe(父子进程共享fd)方式通信,父子进程通信数据的格式定义在compiler/plugin.proto。
- 父进程(protoc进程)中负责读取proto文件,转化为CodeGeneratorRequest格式,启动子进程,以及后续持久化子进程返回内容;
- 子进程(自定义插件进程)完成中子进程中启动自定义的CodeGeneratorResponse格式,按照自己需要完成处理,返回给父进程(protoc进程);
父子进程共享fd工作机制说明:
利用父子进程共享fd机制,建立pipe(单工模式)。
- 子进程一侧,做重定向,将
stdin_pipe[0]
重定向到STDIN_FILENO
,stdout_pipe[1]
重定向到STDOUT_FILENO
,这样plugin处理过程中,无需记录下输入/输出fd; - 父进程一侧,从
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()
的功能:
- 从STDIN_FILENO读取protoc主进程的输入数据,并且反序列化到CodeGeneratorRequest request;
- 从FileDescriptorProto产出FileDescriptor
- 调用MyCodeGenerator::Generate()
- 输出CodeGeneratorResponse response序列化之后的结果到STDOUT_FILENO,提供给protoc主进程
Subprocess类
- 负责建立父子进程之间的pipe,启动子进程
- 完成父子进程之间通信的数据格式转换
上一篇: C语言链表学生信息管理系统
下一篇: c语言实战项目:学生信息管理系统