IDispatch 介面和雙介面

2021-06-05 21:24:19 字數 2325 閱讀 2311

二、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系統,閃...