乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Thrift之代碼生成器Compiler原理及源碼詳細(xì)解析2

       碼農(nóng)書館 2019-04-10

      我的新浪微博:http://weibo.com/freshairbrucewoo。

      歡迎大家相互交流,共同提高技術(shù)。

      2  t_generator類和t_generator_registry類

      這個(gè)兩個(gè)類的主要功能就是為生成所有語言的代碼提供基礎(chǔ)信息和提供具體代碼生成器對(duì)象,上面就是調(diào)用這個(gè)兩個(gè)類的方法來生成具體語言的代碼生成器對(duì)象和執(zhí)行生成代碼的功能函數(shù)。下面主要分析兩個(gè)函數(shù)的功能,一個(gè)是t_generator_registry類的get_generator函數(shù),這個(gè)是一個(gè)靜態(tài)的函數(shù)可以直接通過類調(diào)用;另一個(gè)是t_generator類的generate_program函數(shù)。

      1t_generator_registry類的get_generator函數(shù)

      這個(gè)函數(shù)有兩個(gè)參數(shù),一個(gè)是表示程序的對(duì)象program,另一個(gè)是語言字符串參數(shù)(包括代表語言的簡(jiǎn)短字符串和可選項(xiàng)的組合,有的沒有)。函數(shù)首先解析語言字符串參數(shù),參數(shù)字符串中是這樣組織的:在冒號(hào)(:)之前是代表語言的字符串,冒號(hào)之后是可選項(xiàng)的參數(shù),每一個(gè)可選項(xiàng)參數(shù)用逗號(hào)(,)分割,每一個(gè)可選項(xiàng)參數(shù)都是鍵值對(duì)并且鍵和值是用等號(hào)(=)分割。按照上面的字符串格式解析各個(gè)參數(shù)部分就可以了,可選項(xiàng)參數(shù)用map來保存鍵值對(duì),代碼實(shí)現(xiàn)如下:

      復(fù)制代碼
       1 string::size_type colon = options.find(':');
       2 
       3   string language = options.substr(0, colon);
       4 
       5   map<string, string> parsed_options;
       6 
       7   if (colon != string::npos) {
       8 
       9     string::size_type pos = colon+1;
      10 
      11     while (pos != string::npos && pos < options.size()) {
      12 
      13       string::size_type next_pos = options.find(',', pos);
      14 
      15       string option = options.substr(pos, next_pos-pos);
      16 
      17       pos = ((next_pos == string::npos) ? next_pos : next_pos+1);
      18 
      19       string::size_type separator = option.find('=');
      20 
      21       string key, value;
      22 
      23       if (separator == string::npos) {
      24 
      25         key = option;
      26 
      27        value = "";
      28 
      29       } else {
      30 
      31         key = option.substr(0, separator);
      32 
      33         value = option.substr(separator+1);
      34 
      35      }
      36 
      37       parsed_options[key] = value;
      38 
      39     }
      40 
      41   }
      復(fù)制代碼

       

      然后調(diào)用get_generator_map函數(shù)得到一個(gè)代表語言字符串和產(chǎn)生這種語言生成器對(duì)象的工廠對(duì)象的map對(duì)象:gen_map_t& the_map = get_generator_map(); gen_map_t的定義如下:

      1 typedef std::map<std::string, t_generator_factory*> gen_map_t;

       

      get_generator_map函數(shù)只有兩句代碼,一個(gè)是定義一個(gè)靜態(tài)局部變量并初始化(因?yàn)殪o態(tài)局部變量必須并初始化并且只有第一次會(huì)執(zhí)行初始化,因?yàn)椴怀跏蓟溄映绦虻臅r(shí)候會(huì)報(bào)錯(cuò)),第二句就是返回這個(gè)靜態(tài)局部變量給調(diào)用者,代碼如下:

      1 static gen_map_t* the_map = new gen_map_t();
      2 
      3   return *the_map;

       

      然后在這個(gè)map對(duì)象中找到對(duì)應(yīng)語言的工廠對(duì)象,然后用這個(gè)工廠對(duì)象生產(chǎn)一個(gè)這種語言的代碼生成器對(duì)象并返回給調(diào)用者,代碼如下所示:

      1    gen_map_t::iterator iter = the_map.find(language);
      2 
      3   return iter->second->get_generator(program, parsed_options, options);

       

      本函數(shù)的功能已經(jīng)分析完畢,但是還存在著兩個(gè)問題(或是困難)。一個(gè)是最后一條返回一句是根據(jù)具體的語言來使用具體語言生產(chǎn)器的工廠對(duì)象生產(chǎn)代碼生成器,具體又是怎么生成的了?第二個(gè)就是從main函數(shù)執(zhí)行到現(xiàn)在還沒有發(fā)現(xiàn)在哪兒為get_generator_map函數(shù)里定義的靜態(tài)局部變量添加過任何鍵值對(duì),那么我們查找具體語言必定會(huì)失敗,那么會(huì)返回一個(gè)NULL給調(diào)用者,那么程序就會(huì)執(zhí)行不下去了,但是程序確實(shí)能夠完完整整的執(zhí)行下去,這個(gè)問題困擾了我好一會(huì)兒。下面就這兩個(gè)問題繼續(xù)分析相關(guān)代碼并且解決問題。

      第一個(gè)應(yīng)該不算是問題,但是必須要解決第二個(gè)問題以后才能夠解釋,因?yàn)闆]有解決第二個(gè)問題,那么根本就不會(huì)執(zhí)行到最后一條返回語句這兒來,所以我先解決第二個(gè)問題。

      第二個(gè)問題分析和解決思路如下:

      我們通常認(rèn)為main函數(shù)是程序的入口函數(shù),那么所以程序的執(zhí)行都是從main函數(shù)開始的,所以我也選擇從main函數(shù)開始分析這部分的代碼,根據(jù)程序的執(zhí)行流程閱讀和分析代碼是我一貫的思路。但是這種情況在C++里面有例外,記得我在學(xué)習(xí)MFC的時(shí)候,分析MFC執(zhí)行過程就發(fā)現(xiàn)一個(gè)問題,那就是全局變量的初始化是在main函數(shù)開始之前的,也就是說全局類對(duì)象的構(gòu)造函數(shù)也是在main執(zhí)行之前執(zhí)行的。由于我反復(fù)從main開始一直詳細(xì)的閱讀每一行代碼,所以可以確定確實(shí)沒有在執(zhí)行的過程中初始化the_map靜態(tài)局部變量,所以唯一的可能就是在main函數(shù)開始之前已經(jīng)初始化好了。根據(jù)這一點(diǎn)思路自己開始著手查找初始化the_map的代碼,發(fā)現(xiàn)t_generator_registry類的register_generator函數(shù)為the_map添加鍵值對(duì)了,這個(gè)函數(shù)定義如下:

      復(fù)制代碼
       1 void t_generator_registry::register_generator(t_generator_factory* factory) {
       2 
       3   gen_map_t& the_map = get_generator_map();
       4 
       5   if (the_map.find(factory->get_short_name()) != the_map.end()) {
       6 
       7     failure("Duplicate generators for language \"%s\"!\n", factory->get_short_name().c_str());
       8 
       9   }
      10 
      11   the_map[factory->get_short_name()] = factory;
      12 
      13 }
      復(fù)制代碼

       

      這個(gè)函數(shù)也首先調(diào)用get_generator_map函數(shù)得到那個(gè)靜態(tài)局部變量,然后查找要注冊(cè)的工程是否已經(jīng)在the_map中存在,如果存在就提示失敗信息,否則就把工廠的名字和工廠對(duì)象作為鍵值對(duì)添加到the_map中。

      雖然找到了為the_map添加鍵值對(duì)的地方,但是還沒有找到調(diào)用這個(gè)注冊(cè)工廠函數(shù)的地方,所以繼續(xù)在代碼中搜索調(diào)用這個(gè)函數(shù)的地方。整個(gè)代碼就只有一處調(diào)用了這個(gè)函數(shù),而且是在一個(gè)類的構(gòu)造函數(shù)中,代碼如下:

      復(fù)制代碼
       1 t_generator_factory::t_generator_factory(const std::string& short_name, const std::string& long_name,
       2 
       3     const std::string& documentation) : short_name_(short_name)
       4 
       5   , long_name_(long_name) , documentation_(documentation)
       6 
       7 {
       8 
       9   t_generator_registry::register_generator(this);
      10 
      11 }
      復(fù)制代碼

       

      t_generator_factory類是所有生產(chǎn)代碼生產(chǎn)器對(duì)象工廠的基類,每一種具體的語言都有自己的代碼生成器類和生產(chǎn)這種類的工廠類,上面的代碼是它的構(gòu)造函數(shù),功能就是把自己注冊(cè)到the_map中??吹竭@里是否有一種逐漸清晰的感覺,但是總是感覺還有少點(diǎn)什么,就是這個(gè)構(gòu)造函數(shù)被調(diào)用也必須有這個(gè)類的對(duì)象被定義或其子類的對(duì)象被定義。于是我又開始搜索哪些類是從這個(gè)類繼承的,發(fā)現(xiàn)兩處很重要的代碼,一處如下:

      復(fù)制代碼
       1 template <typename generator>
       2 
       3 class t_generator_factory_impl : public t_generator_factory {
       4 
       5  public:
       6 
       7   t_generator_factory_impl(const std::string& short_name, const std::string& long_name,
       8 
       9          const std::string& documentation) : t_generator_factory(short_name, long_name, documentation)
      10 
      11   {}
      12 
      13 virtual t_generator* get_generator(t_program* program, 
      14 
      15  const std::map<std::string, std::string>& parsed_options, const std::string& option_string) {
      16 
      17     return new generator(program, parsed_options, option_string);
      18 
      19  }
      20 
      21 ……//此處省略了一些代碼
      22 
      23 };
      復(fù)制代碼

       

      t_generator_factory_impl類繼承了t_generator_factory類,而且在構(gòu)造函數(shù)的時(shí)候也調(diào)用了父類的構(gòu)造函數(shù),因?yàn)槭菐?shù)的構(gòu)造函數(shù)所以必須手動(dòng)調(diào)用父類的構(gòu)造函數(shù)。這個(gè)類是一個(gè)模板類,模板參數(shù)就是一個(gè)代碼生成器類,所以函數(shù)get_generator就能夠根據(jù)這個(gè)模板參數(shù)生成new一個(gè)對(duì)應(yīng)語言的代碼生成器對(duì)象了。這里就把上面提到的第一個(gè)問題也解決了,每一個(gè)工廠類把自己注冊(cè)到the_map,然后使用者通過代表語言的鍵(key)在the_map找到對(duì)應(yīng)的工廠對(duì)象,然后調(diào)用get_generator函數(shù)就生成具體的代碼生成器對(duì)象了,這就是第一個(gè)問題提到的最后一句返回語句的代碼執(zhí)行情況。

      但是還是沒有看到定義具體的工廠對(duì)象呀,那么還需要看下面一處的代碼:

      復(fù)制代碼
       1 #define THRIFT_REGISTER_GENERATOR(language, long_name, doc)         2 
       3 class t_##language##_generator_factory_impl                       4 
       5     : public t_generator_factory_impl<t_##language##_generator>     6 
       7   {                                                                 8 
       9    public:                                                         10 
      11     t_##language##_generator_factory_impl()                        12 
      13       : t_generator_factory_impl<t_##language##_generator>(        14 
      15           #language, long_name, doc)                               16 
      17     {}                                                             18 
      19   };                                                               20 
      21   static t_##language##_generator_factory_impl _registerer;
      復(fù)制代碼

       

      這是一個(gè)宏定義,它根據(jù)參數(shù)language定義一個(gè)生產(chǎn)具體語言的代碼生成器的工廠類,并從t_generator_factory_impl類繼承,傳遞的模板參數(shù)也是對(duì)應(yīng)語言的代碼生成器類,構(gòu)造函數(shù)同樣調(diào)用了父類的構(gòu)造函數(shù);最后還定義了一個(gè)對(duì)應(yīng)的靜態(tài)的類全局變量(千呼萬喚始出來,終于找到定義類的全局變量了)。但是還是存在同樣的問題就是定義了宏函數(shù)還是需要調(diào)用才執(zhí)行吧,所以就在代碼中搜索調(diào)用了這個(gè)宏函數(shù)的代碼,最終發(fā)現(xiàn)這個(gè)每一個(gè)具體的語言代碼生成器的文件都調(diào)用了一次,如下面是C++的文件t_cpp_generator.cc中調(diào)用的代碼:

      復(fù)制代碼
      1 THRIFT_REGISTER_GENERATOR(cpp, "C++",
      2 
      3 "    pure_enums:      Generate pure enums instead of wrapper classes.\n"
      4 
      5 "    dense:           Generate type specifications for the dense protocol.\n"
      6 
      7 "    include_prefix:  Use full include paths in generated files.\n"
      8 
      9 )
      復(fù)制代碼

       

      其他語言的代碼生成器類的定義文件中都有類似的調(diào)用,這樣每一個(gè)語言生成器對(duì)象的生產(chǎn)工廠就被注冊(cè)到the_map中了,由此問題得到解決。

      2t_generator類的generate_program函數(shù)

      這個(gè)函數(shù)是生成具體語言代碼的頂層函數(shù),它會(huì)調(diào)用子類定義的各個(gè)子函數(shù)來做具體代碼的生成過程,后面會(huì)詳細(xì)解析C++、javapython代碼生成的過程。

      首先調(diào)用代碼生成器的初始化函數(shù)來初始化代碼生成器,然后依次調(diào)用各種基本數(shù)據(jù)類型和服務(wù)的生成函數(shù)來生成相應(yīng)的代碼,最后關(guān)閉代碼生成器。代碼實(shí)現(xiàn)如下:

       

      復(fù)制代碼
       1  init_generator();
       2 
       3   vector<t_enum*> enums = program_->get_enums();
       4 
       5   vector<t_enum*>::iterator en_iter;
       6 
       7   for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
       8 
       9     generate_enum(*en_iter);
      10 
      11   }
      12 
      13   vector<t_typedef*> typedefs = program_->get_typedefs();
      14 
      15   vector<t_typedef*>::iterator td_iter;
      16 
      17   for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
      18 
      19     generate_typedef(*td_iter);
      20 
      21   }
      22 
      23   vector<t_const*> consts = program_->get_consts();
      24 
      25   generate_consts(consts);
      26 
      27   vector<t_struct*> objects = program_->get_objects();
      28 
      29   vector<t_struct*>::iterator o_iter;
      30 
      31   for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
      32 
      33     if ((*o_iter)->is_xception()) {
      34 
      35       generate_xception(*o_iter);
      36 
      37     } else {
      38 
      39       generate_struct(*o_iter);
      40 
      41     }
      42 
      43   }
      44 
      45   vector<t_service*> services = program_->get_services();
      46 
      47   vector<t_service*>::iterator sv_iter;
      48 
      49   for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
      50 
      51     service_name_ = get_service_name(*sv_iter);
      52 
      53     generate_service(*sv_iter);
      54 
      55   }
      56 
      57   close_generator();
      復(fù)制代碼

       

      此函數(shù)使用的是詞法和語法分析結(jié)果的一些符號(hào),這些符號(hào)都保持在t_program對(duì)象的對(duì)于數(shù)據(jù)結(jié)構(gòu)里面,所以上面的函數(shù)依次從t_program對(duì)象中取得各種數(shù)據(jù)類型的符號(hào)和服務(wù)的符號(hào),并依次生成。

      3t_generator類的其它功能簡(jiǎn)介

      這個(gè)類是所有具體語言代碼生成器的共同基類,所以定義了很多各種語言代碼生成需要的共同功能,例如生成代碼的格式控制、命名空間的有效性檢查、駝峰標(biāo)識(shí)符和下劃線標(biāo)識(shí)符的相互轉(zhuǎn)換等等。這些功能比較簡(jiǎn)單,需要可以直接查看源代碼。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多