讀書問題一:“自動化在許多不同的方面用開發人員編寫的代碼來代替編譯器生成的代碼......” 請問這句話如何理解?(第11章,分發接口與自動化,P231)
答:這句話大意是說:我們原先所寫的應用,都是源碼一級,需要經過編譯器編譯,才能執行,現在,用腳本語言來操作自動化接口,可以動態的完成相同的應用(其實是解釋執行)。
一個簡單的例子,你肯定沒有Word的源碼,如果你想用Word來生成一個針對具體應用領域(比方說政府公文)的應用,你只能找有源碼的公司來修改源碼,以適應你的特殊需要。(微軟聽你的?)
但是,你可以用自動化接口來定制你的特定應用,用VBA腳本來控制Word的自動化接口就可以完成。是的,解釋執行是慢了些,但是,對你來說不用改源碼,不用再去測試你修改的源碼部分,不是更好嗎?
讀書問題二:“若C++程序員想在運行時從頭開始構造一個vtbl,那他可以完全自行決定如何構造。另一方面......” 這段話應如何理解?(第11章,分發接口與自動化,P234)
答:是的,一個VTBLE的生成是由你所用的編譯器替你完成的,但是,如果你明白了 vtbl的構造過程,你可以仿制一個出來。建議讀:《COM本質論》+《Inside C++ Object Model》,要有很好的心理准備,啃硬骨頭。
讀書問題三:OleInitialize 和 CoInitialize(Ex)這兩個函數有什麼區別?
P236倒數第六行有對OleInitialize的調用
答:CoInitialize以及CoInitializeEx 是用來初始化COM運行環境的,就象練武的人在練武前先劃了個圈,在圈裡擺上了兵器。
OleInitialize是初始化Ole的運行環境,Ole是在COM的基礎上作的擴展,是ActiveX運行的基礎。就象是在剛才的圈子裡撐起了個鋼絲,要表演鋼絲上的表演一樣。
讀書問題之四:P208頁,關於對point_default關鍵字的解釋,看不懂:
1、“point_default關鍵字的作用就是告訴MIDL編譯器在沒有為指針指定其它屬性時應如何處理此指針”“其它屬性”都是些什麼?
2、“在函數內部,不能為它們指定別名......”,什麼是別名?
答:至於別名,是指MIDL語言中的typedef吧(非常抱歉,我對COM的調度部分沒有太多的關注,只能簡單回答,請你有了明確的答案後告訴我)。
讀書問題之五:P234最後一句,“當然用COM接口來實現IDispatch::Invoke也是可能的,請參閱圖11-2”
1、用COM接口如何實現Invoke?
2、圖11-2中FooBar不是COM接口吧(沒有IUnknown那三個函數)?
答:COM是更好的C++,COM的實現其實借鑒了很多C++的實現方式,比如,利用我前面所說的vtbl,
按照規定,我覺得我們不應該把圖11-2的FooBar稱為COM接口,但是,在廣義的范圍內,由於使用了vtbl,可以勉強認為他也是一個COM接口,(如果作者非要這樣講的話 ^_^)
讀書問題之六:分發接口是COM接口(符合COM接口的定義嗎)?它跟Invoke函數有何關系?如果不是COM接口,那麼分發接口的定義是什麼?
答:分發接口可以是COM接口,也可以不是,這只是實現時的不同方式而已,分發接口是一個概念,內部應該包含兩個數組,一個存放dispid與接口方法名稱的對值(pair),一個存放的是dispid與接口方法指針(也就是函數指針)的對值。只要有這兩部分我們就認為它是一個分發接口,至於是不是COM接口,那都無所謂。
Invoke的時候,需要提供dispid和對應的參數,這樣,就可以利用分發接口的具體實現機制得到函數指針進行功能調用了。
讀書問題之七: P234第七行:“IDispatch::Invoke的一個實現所實現的函數集被稱作一個分發接口,和dispinterface......”Invoke是一個函數,怎麼能夠實現“函數集”?Invoke函數跟分發接口之間是什麼關系?
答:對於IDispatch::Invoke,我們可以看一下它的運行過程:
在調用Invoke之前,我們通過各種方式得到了一個dispid,(不要以為只有GetIDsOfNames才能得到,我曾經在一個組件裡實現了根據狀態不同,將可執行的dispid動態傳出,然後在組件內提供了一個方法,ExecuteCmd(dispid),這樣客戶程序也可以動態執行組件的接口方法了)。接口的本質就是一組函數指針的數組,而dispid就是函數指針數組的索引(注意,只有實現IDispatch接口才有dispid),通過指定索引,我們可以得到指定的函數指針,這樣我們可以用(*函數指針)(參數,參數…)的方式來調用具體的接口方法了。
“等等......”我聽見你在喊,“我們的參數是以數組的形式傳進來的,而你用函數指針調用的時候是用參數列表的形式調用的,我要怎樣才能實現它呢?”
是的,如果要你自己寫一個Invoke的實現,光參數的壓棧和類型處理就會累死你的,告訴你一個好辦法,用MS的API函數(DispCallFunc 或者 DispInvoke),或者用使用MFC/ATL對IDispatch實現的封裝()(MFC用的是一個helper,而ATL用的是IDispatchImpl模版)。
分發接口是一個邏輯概念,它是指有個地方存放了函數方法名和函數的指針,通過這個接口,你可以用指定的方法名來檢索到函數的指針,最大的用處,是提供給腳本解釋器使用。