<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

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

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

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

      2  t_generator類和t_generator_registry類

      這個兩個類的主要功能就是為生成所有語言的代碼提供基礎信息和提供具體代碼生成器對象,上面就是調用這個兩個類的方法來生成具體語言的代碼生成器對象和執行生成代碼的功能函數。下面主要分析兩個函數的功能,一個是t_generator_registry類的get_generator函數,這個是一個靜態的函數可以直接通過類調用;另一個是t_generator類的generate_program函數。

      1t_generator_registry類的get_generator函數

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

       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   }

       

      然后調用get_generator_map函數得到一個代表語言字符串和產生這種語言生成器對象的工廠對象的map對象: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函數只有兩句代碼,一個是定義一個靜態局部變量并初始化(因為靜態局部變量必須并初始化并且只有第一次會執行初始化,因為不初始化鏈接程序的時候會報錯),第二句就是返回這個靜態局部變量給調用者,代碼如下:

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

       

      然后在這個map對象中找到對應語言的工廠對象,然后用這個工廠對象生產一個這種語言的代碼生成器對象并返回給調用者,代碼如下所示:

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

       

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

      第一個應該不算是問題,但是必須要解決第二個問題以后才能夠解釋,因為沒有解決第二個問題,那么根本就不會執行到最后一條返回語句這兒來,所以我先解決第二個問題。

      第二個問題分析和解決思路如下:

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

       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 }

       

      這個函數也首先調用get_generator_map函數得到那個靜態局部變量,然后查找要注冊的工程是否已經在the_map中存在,如果存在就提示失敗信息,否則就把工廠的名字和工廠對象作為鍵值對添加到the_map中。

      雖然找到了為the_map添加鍵值對的地方,但是還沒有找到調用這個注冊工廠函數的地方,所以繼續在代碼中搜索調用這個函數的地方。整個代碼就只有一處調用了這個函數,而且是在一個類的構造函數中,代碼如下:

       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 }

       

      t_generator_factory類是所有生產代碼生產器對象工廠的基類,每一種具體的語言都有自己的代碼生成器類和生產這種類的工廠類,上面的代碼是它的構造函數,功能就是把自己注冊到the_map中。看到這里是否有一種逐漸清晰的感覺,但是總是感覺還有少點什么,就是這個構造函數被調用也必須有這個類的對象被定義或其子類的對象被定義。于是我又開始搜索哪些類是從這個類繼承的,發現兩處很重要的代碼,一處如下:

       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 };

       

      t_generator_factory_impl類繼承了t_generator_factory類,而且在構造函數的時候也調用了父類的構造函數,因為是帶參數的構造函數所以必須手動調用父類的構造函數。這個類是一個模板類,模板參數就是一個代碼生成器類,所以函數get_generator就能夠根據這個模板參數生成new一個對應語言的代碼生成器對象了。這里就把上面提到的第一個問題也解決了,每一個工廠類把自己注冊到the_map,然后使用者通過代表語言的鍵(key)在the_map找到對應的工廠對象,然后調用get_generator函數就生成具體的代碼生成器對象了,這就是第一個問題提到的最后一句返回語句的代碼執行情況。

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

       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;

       

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

      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 )

       

      其他語言的代碼生成器類的定義文件中都有類似的調用,這樣每一個語言生成器對象的生產工廠就被注冊到the_map中了,由此問題得到解決。

      2t_generator類的generate_program函數

      這個函數是生成具體語言代碼的頂層函數,它會調用子類定義的各個子函數來做具體代碼的生成過程,后面會詳細解析C++javapython代碼生成的過程。

      首先調用代碼生成器的初始化函數來初始化代碼生成器,然后依次調用各種基本數據類型和服務的生成函數來生成相應的代碼,最后關閉代碼生成器。代碼實現如下:

       

       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();

       

      此函數使用的是詞法和語法分析結果的一些符號,這些符號都保持在t_program對象的對于數據結構里面,所以上面的函數依次從t_program對象中取得各種數據類型的符號和服務的符號,并依次生成。

      3t_generator類的其它功能簡介

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

      posted @ 2012-04-25 00:24  薔薇理想人生  閱讀(2759)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲成人av一区二区| 无码中文字幕人妻在线一区二区三区 | 一本之道高清乱码少妇| 99国产精品白浆在线观看免费| 人成午夜免费大片| 九九热免费公开视频在线| 久久91精品牛牛| 国产福利永久在线视频无毒不卡| 日本高清在线观看WWW色| 国产午夜亚洲精品久久| 国产SM重味一区二区三区| 国产无遮挡吃胸膜奶免费看| 国产精品国产亚洲看不卡| 东台市| 国产日韩一区二区在线| 成人性生交片无码免费看| 忘忧草影视| 美腿丝袜亚洲综合第一页| 少妇扒开双腿自慰出白浆| 五月婷之久久综合丝袜美腿| 67194熟妇在线观看线路| 亚洲偷自拍国综合| 亚洲国产欧美在线看片一国产| 青柠影院免费观看高清电视剧丁香 | 熟女蜜臀av麻豆一区二区| 亚洲日韩一区二区| 国产强奷在线播放免费| 容城县| 人妻丝袜无码专区视频网站| 国产亚洲精品久久综合阿香| 激情自拍校园春色中文| 亚洲欧洲一区二区免费| 性色av极品无码专区亚洲| 国产精品国产三级国快看| 99精品热在线在线观看视| 色婷婷亚洲精品综合影院| 少妇人妻挤奶水中文视频毛片| 成在线人免费| 久久精品国产88精品久久| a级国产乱理伦片在线观看al| 欧美成人一区二区三区不卡|