二、idispatch 介面和雙介面
使用者要想呼叫普通的 com 元件功能,必須要載入這個元件的型別庫(type library)檔案 tlb(比如在 vc 中使用 #import)。然而,在指令碼程式中,由於指令碼是被解釋執行的,所以無法使用載入型別庫的方式進行預編譯。那麼指令碼直譯器如何使用 com 元件那?這就是自動化(idispatch)元件大顯身手的地方了。
idispatch
介面需要實現4個函式,呼叫者只通過這4個函式,就能實現呼叫自動化元件中所有的函式。這4個函式功能如下:
hresult gettypeinfocount(
[out] uint * pctinfo)
元件中提供幾個型別庫?當然一般都是乙個啦。
但如果你在乙個元件中實現了多個 idispatch 介面,那就不一定啦(注1)
hresult gettypeinfo(
[in] uint itinfo,
[in] lcid lcid,
[out] itypeinfo ** pptinfo)
呼叫者通過該函式取得他想要的型別庫。
幸好,在 99% 的情況下,我們都不用關心這兩個函式的實現,因為 mfc/atl 都幫我們完成了預設的乙個實現,如果是自己完成函式**,甚至可以直接返回 e_notimpl 表示沒有實現。(注2)
hresult getidsofnames(
[in] refiid riid,
[in,size_is(cnames)] lpolestr * rgsznames,
[in] uint cnames,
[in] lcid lcid,
[out,size_is(cnames)] dispid * rgdispid)
根據函式名稱取得函式序號,為呼叫 invoke()做準備。
所謂函式序號,大家去觀察雙介面 idl 檔案和 mfc 的 odl 檔案,每乙個函式和屬性都會有[id(序號)....] 這樣的描述。
hresult invoke(
[in] dispid dispidmember,
[in] refiid riid,
[in] lcid lcid,
[in] word wflags,
[in,out] dispparams * pdispparams,
[out] variant * pvarresult,
[out] excepinfo * pexcepinfo,
[out] uint * puargerr)
根據序號,執行函式。
使用 mfc/atl 寫的元件程式,我們也不必關心這個函式的實現。如果是自己寫**,則該函式類似如下實現:
switch(dispidmember)
其實,就是根據序號進行分支呼叫啦。(注3)
從 invoke() 函式的實現就可以看出,使用 idispatch 介面的程式,其執行效率是比較低的。atl 從效率出發,實現了一種叫「雙介面(dual)」的介面模式。下面我們來看看,到底什麼是雙介面:
圖一、雙介面(dual)結構示意圖
從上圖中可以看出,所謂雙介面,其實是在乙個 vtab 的虛函式表中容納了三個介面(因為任何介面都是從 iunknown 派生的,所以就不強調 iunknown 了,叫做雙介面)。我們如果從任意乙個介面中呼叫 queryinte***ce()得到另外的介面指標的話,其實,得到的指標位址都是同乙個。雙介面有什麼好處那?答:好呀,多好呀,特別好呀......
使用方式
因為
所以
指令碼語言使用元件
直譯器只認識 idispatch介面
可以呼叫,但執行效率最低
編譯型語言使用元件
它認識 idispatch介面
可以呼叫,執行效率比較低
編譯型語言使用元件
它裝載型別庫後,就認識了 i*** 介面
可以直接呼叫 i*** 函式,效率最高啦
結論
雙介面,既滿足指令碼語言的使用方便性,又滿足編譯型語言的使用高效性。
於是,我們寫的所有的 com 元件介面,都用雙介面實現嗎?
錯!否!no!
如果不是明確非要支援指令碼的呼叫,則最好不要使用雙介面,因為:
如果所有函式都放在乙個雙介面中,那麼層次、結構、分類不清
如果使用多個雙介面,則會產生其它問題(注4)
雙介面、idispatch介面只支援自動化的引數型別,使用受到限制,某些情況下很不方便嘍
還有很多弊病呦,不過現在我想不起來嘍......
IDispatch介面元件的簡單實現
math.h math.h access to the global variables extern dword g dwobjs extern dword g dwlocks define guid clsid math,0xa988bd40 0x9f1a 0x11ce 0x8b 0x9f 0x...
List介面 Set介面和Map介面
1 list和set介面自collection介面,而map不是繼承的collection介面 collection表示一組物件,這些物件也稱為collection的元素 一些 collection允許有重複的元素,而另一些則不允許 一些collection是有序的,而另一些則是無序的 jdk中不提...
VC介面繪製雙快取
1 閃屏的問題 在gdi的繪圖系統中,每呼叫一次區域繪圖操作,如fillrect bitblt等,圖形顯示系統就會在螢幕中對指定的區域進行一次重新整理操作。如果頻繁的進行區域繪製操作的操作的話,我們就會發現,螢幕會出現閃屏。使用下面的 對閃屏的問題進行測試,在xp系統閃屏尤其嚴重,在win7系統,閃...