久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

IDispatch

 昵稱225033 2014-01-05
IDispatch是由OLE自動化協(xié)議暴露出來的接口,。它是COM對象可以暴露出來的標(biāo)準(zhǔn)接口(Interface)之一(IDispatch最前面的“I”代表Interface),。COM可以由三種接口類型予以區(qū)分,它們是自定義接口(custom),,調(diào)度接口(dispatch)和雙重接口(dual interfaces),。

  IDispatch可以由IUnknown得到,并且在IUnknown本身所含有三個方法(AddRef,,Release和QueryInterface)上增加另外四個方法(GetTypeInfoCount,,GetTypeInfo,GetIDsOfNames和Invoke),。

自動化接口IDispatch允許客戶端程序探明一個運行中的對象到底支持什么屬性和方法,。


IDispatch接口的作用

(2007-01-25 16:24:27)

網(wǎng)上說法1:

IDispatch 接口是COM中比較常用的接口。

如果某個COM對象繼承了IDispatch接口,,那么這個COM對象所有的方法和屬性都可以以它們的名稱為參數(shù),,通過調(diào)用IDispatch接口的Invoke()方法來間接調(diào)用這些方法和屬性。

在ATL中,,如果想使某個COM對象支持IDispatch接口,,那么必須在這個COM對象的屬性中指定DUAL,,即具有雙重接口屬性。在支持IDispatch接口的COM對象中,,每個屬性和方法都有一個唯一的DispID(這可以通過一個宏來獲得),,客戶端可以以方法的名稱為參數(shù)調(diào)用IDispatch接口的GetIDsOfNames()來獲得這個DispID,然后以這個DispID為參數(shù)調(diào)用IDispatch接口的Invoke()函數(shù)來間接調(diào)用COM對象中方法,,并獲得返回結(jié)果,。有意思的是,COM對象中DispID為0的方法是默認的方法,,即客戶調(diào)用IDispatch接口的Invoke()時如果沒有給出DispID參數(shù),,則默認調(diào)用的是這個方法。

 我猜測在COM子系統(tǒng)內(nèi)部是這樣支持通過名字調(diào)用COM對象方法的:首先調(diào)用IDispatch接口的GetIDsOfNames()獲得該方法的DispID,,這實際上是一個查表的操作,,然后調(diào)用IDispatch接口的Invoke()函數(shù)來間接調(diào)用這個方法,這同樣要先通過DispID來查表獲得相應(yīng)的方法入口地址,,然后執(zhí)行這個方法,,獲得可能的返回結(jié)果,再將這個結(jié)果傳遞到客戶端,。

 

設(shè)計IDispatch接口的本意是為了在VB和VBScript中使用COM,,因為這樣的語言不支持指針,所以不能像C++那樣直接通過指向?qū)ο蟮闹羔榿慝@得COM對象方法的入口,,只能通過COM子系統(tǒng)來調(diào)用COM對象中的方法,。實際上,在VB中調(diào)用COM對象的方法時,,COM子系統(tǒng)會自動根據(jù)VB給出的函數(shù)名,,調(diào)用該COM對象IDispatch接口的Invoke()方法來間接調(diào)用該方法,并將結(jié)果返回VB,。當(dāng)然這個過程對程序員來將是透明的,,所以給人的感覺就像是由VB調(diào)用了COM對象的方法一樣。

 盡管在客戶端看不出IDispatch接口的作用,,可是在設(shè)計COM對象時卻要考慮是否要支持IDispatch接口這個問題,,如果支持則可以擴大該COM對象的使用范圍,,但對COM的性能會有一定的影響,,如果這個COM對象規(guī)模比較大的話,通過IDispatch接口調(diào)用該對象的方法會耗費更多的時間,,效率會損失10%-100%,,原因是IDispatch接口通過方法名來查找它的DispID會需要較多的時間。

在ATL中同樣也有一個IDispatch接口指針的封裝類:CComDispatchDriver,。你可以用一個IDispatch接口指針來初始化一個CComDispatchDriver對象,,這個對象提供了一組方法來幫助你使用IDispatch接口指針,。

網(wǎng)上說法2:

支持自動化。
用戶只要有COM庫,,不需要任何說明,, 便可知道該庫所有對象及對象的方法屬性,及方法,、屬性的參數(shù),、返回值 類型,及其ID,。利用IDispatch,,用戶不需要獲得COM
組件的方法實際指針。因為IDispatch::Invoke 提供了一切方法,。這就是為什么叫做 dispatch(分發(fā))接口的原因,。如果沒有IDispatch開發(fā)者必須提供 該COM虛類的原形。現(xiàn)在的大多數(shù)公用COM都被設(shè)計為支持IDispatch接口

網(wǎng)上說法3:

有實現(xiàn)IDispatch的接口組件才能夠被腳本語言這種需要遲綁定使用COM組件使用,,因為腳本語言和VB某種情況下是解釋的方式使用組件的,,稱為遲綁定。而向VC這些語言使用COM組件時,,對組件的調(diào)用方式是在編譯期間決定的,,稱為早綁定。不管怎么樣,,反正各種開發(fā)COM組件的環(huán)境都支持直接實現(xiàn)Idispatch而不需要你做一點多余的工作,,何樂而不為呢?

網(wǎng)上說法4:

Automation was built based on COM. A automation server is a COM component with IDispatch in fact, and A automation controler is a COM Client communated to automation server by IDispath. In a word, IDispatch will accept a name of function and execute it.

GetIDsOfNames & Invoke are the most interest function of IDispatch. GetIDsOfNames will read a name of function and return it's DISPID.then Automation will transfer the DISPID to Invoke. Invoke regard DISPID as the index of function ptr array and loop the function to execute it.

See the defination by IDL(Microsoft):
interface IDispatch : IUnknown
{
......

HRESULT GetIDsOfNames(
[in] const IID& riid,
[in, size_is(cNames)] LPOLESTR* rgszNames,
[in] UINT cNames,
[in] LCID lcid,
[out, size_is(cNames)] DISPID* rgDispd);

HRESULT Invoke(
[in] DISPID dispIdMember,
[in] const IID& riid,
[in] LCID lcid,
[in] WORD wFlags,
[in,out] DISPPARAMS* pDispParams,
[out] VARIANT* pVarResult,
[out] EXCEPINFO* pExcepInfo,
[out] UINT* puArgErr);
......
}

網(wǎng)上說法5:

我的理解是:IDispatch接口又稱為分發(fā)接口,,任何從該接口派生的接口,,可以利用IDispatch的成員函數(shù)來實現(xiàn):1、ID綁定,,即假設(shè)你知道你的接口方法的綁定號(dispID),,則可以直接調(diào)用從IDispatch接口繼承的函數(shù)Invoke(dispID,...)來調(diào)用你的方法。注意,,此時你的接口的許多方法間接通過Invoke函數(shù)來分發(fā)實現(xiàn),,而在你的接口中,則不用實現(xiàn)該函數(shù)聲明及實現(xiàn),。
2,、遲綁定,假定你連方法的dispID都不知道,,此時可以通過方法名來調(diào)用方法,,過程如下,實現(xiàn)調(diào)用從IDispatch接口繼承的函數(shù)GetIDsOfName(...)來查詢特定方法名對應(yīng)的dispID值,,接著調(diào)用Invoke函數(shù)來調(diào)用該方法即可,。
與風(fēng)分發(fā)接口對應(yīng)的是VTable接口,,即前綁定,在編譯時刻就根據(jù)接口的Vtbale地址實現(xiàn)綁定,,雖然這樣效率比其他綁定方式要高,,但缺乏靈活性,尤其在Vb,、vbscrip以及java這樣的語言環(huán)境中,,由于數(shù)據(jù)類型的差異,很難調(diào)用前綁定方式實現(xiàn)的組件接口,。
 
 

COM編程技術(shù)基礎(chǔ)之四

yesky2004-02-02 10:35我要吐槽

  所謂自動化對象,,指的是實現(xiàn)了IDispatch接口的COM對象,IDispatch接口是自動化對象的一個重要標(biāo)志,。使用自動化技術(shù)的一個主要目的就是對COM的一些底層操作進行簡化,。包括自動化組件和自動化客戶兩方面的內(nèi)容,分別用來定義和使用自動化對象,。 自動化對象包含有屬性和方法這兩種重要的組成,。屬性類似于類中的數(shù)據(jù)成員,方法則類似于類成員函數(shù),,只不過這里的屬性只能被讀取而不允許被寫入,。自動化組件除了定義自動化對象外,還將內(nèi)部可編程對象展現(xiàn)給自動化客戶,,而自動化客戶則對這些暴露的自動化對象進行操作,。具體的操作包括:創(chuàng)建一個新的自動化對象,獲取,、設(shè)置自動化對象的屬性,,以及調(diào)用自動化對象的方法等。IDispatch接口作為自動化對象的重要特征,,可以通過QuereyInterface()函數(shù)查詢此接口來確定組件是否是自動化對象,。IDispatch接口直接從IUnknown接口派生,接口定義如下:

interface IDispatch : IUnknown
{
 virtual HRESULT GetTypeInfoCount(UINT* pctinfo) = 0;
 virtual HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) = 0;
 virtual HRESULT GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) = 0;
 virtual HRESULT Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr ) = 0;
}

  其中,,接口成員函數(shù)GetTypeInfoCount()用于獲取自動化組件支持的ITypeInfo接口的數(shù)目,。GetTypeInfo()用于獲取指針I(yè)TypeInfo接口的指針,通過該指針將能夠判斷自動化服務(wù)程序所提供的自動化支持,。剩下的這兩個函數(shù)是比較重要的,,其中GetIDsOfNames()將讀取一個函數(shù)的名稱并返回其調(diào)度ID(DISPID),DISPID只是一個long類型的數(shù)據(jù),,對于IDispatch的一個特定實現(xiàn),,此DISPID值應(yīng)該是唯一的,。其參數(shù)riid為保留參數(shù),,必須設(shè)置為IID_NULL,,在rgszNames中指定了成員的函數(shù)名及其參數(shù),由cNames標(biāo)識了名字的個數(shù),,lcid參數(shù)用于指定本地化標(biāo)識,,得到的DISPID 將保存到rgdispid中。Invoke()提供了訪問自動化對象暴露出來的方法和屬性的方法,??梢詫ISPID作為函數(shù)指針數(shù)組的索引傳入dispidMember參數(shù),Invoke()將實現(xiàn)一組按此索引來訪問的函數(shù),。riid和lcid的含義與在GetIDsOfNames()中的定義相同,,分別為保留參數(shù)和本地化標(biāo)識。WFlags參數(shù)指定了要訪問的是接口的屬性還是方法,,pdispparams參數(shù)包括了方法和屬性調(diào)用的參數(shù)數(shù)組,、DISPID數(shù)組以及數(shù)組中參數(shù)個數(shù)等信息。pvarResult參數(shù)保存有返回值信息,。pexcepinfo指向一個有效的異常信息結(jié)構(gòu),,puArgErr參數(shù)包含了第一個產(chǎn)生錯誤的參數(shù)指針。通過GetIDsOfNames()和Invoke()的結(jié)合使用,,將可以根據(jù)函數(shù)名稱對方法和屬性進行調(diào)用,。這樣,函數(shù)地址,、AddRef(),、Release()以及接口指針等細節(jié)問題將無需考慮。下面結(jié)合一段實例代碼來說明對IDispatch接口的使用:

// 從ProgID得到CLSID
wchar_t progid[] = L"MSCAL.Calendar.7";
CLSID clsid;
if (FAILED(::CLSIDFromProgID(progid, &clsid)))
 return;
 // 得到IDispatch接口指針
IDispatch* pIDispatch = NULL;
if (FAILED(::CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pIDispatch)))
 return;
// 得到DISPID
DISPID dispid;
OLECHAR* func = L"Today";
if (FAILED(pIDispatch->GetIDsOfNames(IID_NULL, &func, 1, GetUserDefaultLCID(), &dispid)))
 return;
// 通過DISPID使用Today方法
DISPPARAMS dispparams = {NULL};
if (FAILED(pIDispatch->Invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &dispparams, NULL, NULL, NULL)))
 return;
// 將日期移動到今天
AfxMessageBox("日期成功移動到今天");

  這段代碼使用的是Calendar組件,,并通過IDispatch接口完成對Today()方法的調(diào)用,。CLSIDFromProgID()將Calendar組件的ProgID轉(zhuǎn)換為CLSID,并以此CLSID和IID_IDispatch作為參數(shù)去調(diào)用CoCreateInstance()以得到IDispatch接口指針,。通過其成員函數(shù)GetIDsOfNames()得到將要調(diào)用的Today方法的DISPID,,最后使用Invoke()成員函數(shù)執(zhí)行此方法。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多