最近所想和所做

    好久沒寫博客了,原因之一是最近習慣了用evernote去記錄自己所想和所看的,另外一個原因是CSDN關閉了live writer的寫blog的功能後,就沒多大興趣在csdn的網頁編輯框裏面寫東西了,一來崩潰了寫的東西全部丟了,一來手機上不好寫。CSDN的標題是“全球最大中文IT社區,爲IT專業技術人員提供最全面的信息傳播和服務平臺”,但我覺得現在的CSDN並不是面向於IT人員了,對於IT人員,特別是程序員而言,界面美不美觀,操作好不好倒是其次,但功能沒有確是不行的。CSDN的改版關閉了blog的很多功能,使得我也沒多大興趣在CSDN上寫Blog了。
    最近在空閒時間在做一個東西:給C++添加元數據,添加反射功能,添加函數的聚合能力。
    大致做法是:用clang分析c++頭文件,然後通過AST生成元數據。clang的AST裏面信息非常豐富,例如結構體的大小,類的信息,函數參數信息,函數的調用方式(例如__cdecl,__stdcall)等都可以獲取到,這樣根據c++生成MetaData時,不需要像COM那樣還需要寫IDL文件。
    反射功能其實就是對元數據進行訪問,然後根據元數據調整堆棧,然後call就可以了。
    函數的聚合能力主要是想實現一種類似於windows的HOOK機制,可以將多個函數附加在一個函數上,當這個函數被調用,附加在這個函數上的函數也會被調用。一個容易理解的例子就是:我們通常會寫一些函數,但有時候會添加log功能,需要在這個函數調用之前或之後打log,這時一種簡便的方法就是將log函數聚合到這個函數上。函數的聚合能力與Aspect編程裏面的Aspect比較像。我做函數的聚合能力主要是想用於以下幾個地方:1. 插件 2. Webkit中渲染時動態添加特效 3. 回調(callback)。對我而言,回調其實是函數聚合的一種特例,只不過被聚合的函數是一個空函數而已。例如js裏面常見onclick callback,其實可以將onclick看作節點對於c++實現裏面的一個方法,只不個這個方法是一個空實現,註冊回調時,其實就是將一些函數聚合到onclick這個方法上,當onclick被調用時,註冊的回調函數也會被調用。
    還有一個基本準則是:不改變現有的C++語法,不改變編譯器實現,而是用外部工具做處理(也就是預編譯),例如用Clang分析頭文件然後生成元信息,用專門的lib或dll工具分析lib或dll,以便在鏈接時做一些事情。這樣做的好處是可以最大程度地使得現有的C++程序可以利用這些特性。當然利用這些特性時,調用方式上也會做一些變動,例如原來是foo.bar(1234)會改成wrapper<foo>.bar(1234)。這裏面的wrapper其實是一個模板,是在生成元數據時一塊生成的。這個在Elastos裏面叫做夾壁牆代碼,我覺得這是一個比較直觀的形容。
    這個東西的另外一個好處是:外部工具做處理(也就是預處理)可以對很多地方做優化,例如反射時函數堆棧調整,參數轉換。因爲這個信息在編譯時就已經確定,運行時也不會改變,就沒必要去動態獲取了。這樣做一個壞處是程序的大小會稍微變大,但現在的內存一般夠用,所以用空間換取時間是值得的。
    上面說道參數轉換,其實我是想實現一種通用些的參數轉換方式,例如js調用C++或者java調用C++時,C++有元信息只是做到了第一步,還需要對參數做轉換。所謂參數轉換,其實就是將一種類型A轉換爲另外一種類型B,我們可以寫一個函數A2B(a, b)去實現這個轉換。類型A是可以轉換爲其他幾種類型的,但一般是可以轉換爲一個基本類型(例如int,char×)或者幾種基本類型的集合,而某種基本類型是可以轉換爲類型B的。因此類型轉換可以被看成圖論裏面的路徑,效率最高的轉換其實就是最短路徑。這樣我們只需要寫類型A和基本類型的轉換函數,那麼類型A和其他類型的轉換是可以通過預處理生成的。每條路徑的cost是通過預處理時得到的:也就是將這個函數編譯進一個測試函數,然後運行,得出的運行時間就是cost。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章