前言
thrift文章整理:
1.thrift简介
2.thrift源码解析之compiler
3.thrift源码解析之processor
4.thrift源码解析之protocol
5.thrift源码解析之transport
6.thrift源码解析之server
thrift框架的compiler采用flex来生成词法分析代码。flex通过编译thriftl.ll生成thriftl.cc文件,thriftl.cc即是该compiler的词法分析代码。
flex内容看:https://blog.csdn.net/weixin_44705391/article/details/115545618?spm=1001.2014.3001.5501
采用bison来生成语法分析代码。bison通过编译thrifty.yy生成thrifty.h和thrifty.cc文件,这两个文件即是该compiler的语法分析代码。
bison内容看:https://blog.csdn.net/weixin_44705391/article/details/115555161?spm=1001.2014.3001.5501
流程
流程图:
main函数主要做的事情如上:
- 解析命令:
解析命令行的命令,得到文件的相关信息和要生成的语言,文件的相关信息主要有:文件路径,产物的输出路径
解析命令的关键变量:
out_path;
//存放生成代码的输出路径,会被放到program里面
vector<string> generator_strings;
//保存执行程序传进来的参数,存储着 需要产生什么语言的文件 的信息
t_program* program
//idl文件的所有信息,thrift中就是我们写的.thrift文件。根据命令传进来的参数所得
有了generator_strings和program就可以调用parse和generate了。
- parse(program, nullptr);
大致步骤: - 提取内嵌IDL文件
- 递归调用parse解析内嵌IDL文件
- 解析IDL文件内容
解析ILD文件内容步骤:
//首先main中定义了一个全局变量FILE *yyin,
//然后打开文件:
yyin = fopen(path.c_str(), "r");
//初始化一些全局变量供yyparse使用:
g_parse_mode = PROGRAM;
g_program = program;
g_scope = program->scope();
g_parent_scope = (parent_program != nullptr) ? parent_program->scope() : nullptr;
g_parent_prefix = program->get_name() + ".";
g_curpath = path;
//调用thrifty.cc中的yyparse
yyparse;
//关闭文件
fclose(yyin);
经过yyparse之后program中就存放了IDL解析之后的符号,数据类型等各种信息,(全局变量g_program中也存放了一份)供接下来的generate使用。
- generate(program, generator_strings);
大致步骤: - 递归调用generate每一个内嵌的program
- 根据generator_strings中提供的要生成的语言拿出一个generator
t_generator* generator = t_generator_registry::get_generator(program, *iter); - 生成这个语言的代码:
generator->generate_program(); - delete generator
2.generate细节
1.generate的get_generator细节:
main函数完结,在generate的第二步中要取generator, t_generator_registry::get_generator的细节:
gen_map_t& the_map = get_generator_map();
gen_map_t::iterator iter = the_map.find(language);
return iter->second->get_generator(program, parsed_options, options);
在the_map中应该是要存放各种语言的factory,然而main完结了都没看到在哪存了the_map。
grep the_map发现t_generator_registry::register_generator填充了the_map,
而此函数被t_generator_factory::t_generator_factory调用,是t_generator_factory的构造函数。那就是说一生成factory就会去填充the_map。需要有此类或者此类的子类对象生成。
发现t_generator_factory_impl
继承了t_generator_factory
,
t_##language##_generator_factory_impl
继承了t_generator_factory_impl
,
t_##language##_generator_factory_impl
宏定义如下:
#define THRIFT_REGISTER_GENERATOR(language, long_name, doc) \
class t_##language##_generator_factory_impl \
: public t_generator_factory_impl<t_##language##_generator> { \
public: \
t_##language##_generator_factory_impl() \
: t_generator_factory_impl<t_##language##_generator>(#language, long_name, doc) {} \
}; \
static t_##language##_generator_factory_impl _registerer;
最终static t_##language##_generator_factory_impl _registerer;定义了一个静态全局变量,而这个宏在每个语言的generator文件下都会执行一遍,使构造函数得以在main之前执行,使得the_map被填充。
其中全局变量_registerer在每个语言文件下都定义了一遍,但是grep发现没有使用,应该只是为了用来执行构造函数。
2.generate的generate_program细节:
以下函数主要做的事情在每个语言的generator文件下,比如t_cpp_generator.cpp
主要做的事情:
- init_generator //1.新建文件夹
//2.获得文件名并打开文件
//3.文件流填充一些通用的内容 - generate_数据类型 //调用各种数据类型生成函数,将这些内容写入文件
3.close_generator
3.类关系
4.文件路径
thrift-0.14.1\compiler\cpp\src\thrift\:
main.cc
thriftl.ll
thriftl.cc
thrifty.yy
thrifty.hh
thrifty.cc
thrift-0.14.1\compiler\cpp\src\thrift\generate:
t_generator.h
t_generator.cc
t_generator_registry.h
t_oop_generator.h
各个语言的生成代码t_语言_generator.cc
类
t_generator类地址:compiler\cpp\src\thrift\generate\t_generator.h
参考文章:
https://www.cnblogs.com/brucewoo/archive/2012/04/24/2467355.html