ATL Internals 2ed复习.chapter 8.COM Collection and Enumeration Interfaces

来源:互联网 发布:linux查看守护进程 编辑:程序博客网 时间:2024/05/21 12:47

COM Collection接口定义类似于:

[ object, dual ]template <typename T>interface ICollection : IDispatch {  [propget]  HRESULT Count([out, retval] long* pnCount);  [id(DISPID_VALUE), propget]  HRESULT Item([in] long n, [out, retval] T* pnItem);  [id(DISPID_NEWENUM), propget]  HRESULT _NewEnum([out, retval] IUnknown** ppEnum);};

由于没有办法确定集合中包含的何种元素,上述是假想定义,假想IDL支持template,值得注意的是这个接口要支持IDispatch

COM Enum接口定义类似于:

template <typename T>interface IEnum : IUnknown {  [local]  HRESULT Next([in] ULONG celt,               [out] T* rgelt,               [out] ULONG *pceltFetched);  [call_as(Next)] // Discussed later...  HRESULT RemoteNext([in] ULONG celt,                     [out, size_is(celt),                      length_is(*pceltFetched)] T* rgelt,                     [out] ULONG *pceltFetched);  HRESULT Skip([in] ULONG celt);  HRESULT Reset();  HRESULT Clone([out] IEnum<T> **ppenum);}

同样是假想定义

 

实际中的ICollection定义为:

[dual]interface IPrimeNumbers : IDispatch {  HRESULT CalcPrimes([in] long min, [in] long max);  [propget]  HRESULT Count([out, retval] long* pnCount);  [propget, id(DISPID_VALUE)]  HRESULT Item([in] long n, [out, retval] long* pnPrime);  [propget, id(DISPID_NEWENUM)] // Not quite right...  HRESULT _NewEnum([out, retval] IEnumPrimes** ppEnumPrimes);};

而实际中IEnum定义为:

interface IEnumPrimes : IUnknown {  [local]  HRESULT Next([in] ULONG celt,               [out] long* rgelt,               [out] ULONG *pceltFetched);  [call_as(Next)]  HRESULT RemoteNext([in] ULONG celt,                     [out, size_is(celt),                       length_is(*pceltFetched)] long* rgelt,                     [out] ULONG *pceltFetched);  HRESULT Skip([in] ULONG celt);  HRESULT Reset();  HRESULT Clone([out] IEnumPrimes **ppenum);};

 

Dealing with the Enumerator local/call_as Oddity

Next有两种Local和Remote

Local允许pceltFetched为NULL

Remote不允许pceltFetched为NULL

对于Proxy过来的请求,需要在proxy-stub实现时加上一段代码,书上给出了使用cpp_quote在idl文件中添加这个例程的手段。

 

Enumeration and Visual Basic 6.0

如果IEnum要支持VB的for each指令,ICollection必须要继承IDispatch而且必须要有_NewEnum和作为DISPID的DISPID_NEWENUM,VB代码就是调用Invoke(DISPID_NEWENUM)来实现的。例如:

[dual]interface IPrimeNumbers : IDispatch {  HRESULT CalcPrimes([in] long min, [in] long max);  [propget]  HRESULT Count([out, retval] long* pnCount);  [propget, id(DISPID_VALUE)]  HRESULT Item([in] long n, [out, retval] long* pnPrime);  [propget, id(DISPID_NEWENUM)]  HRESULT _NewEnum([out, retval] IUnknown** ppunkEnum);};

如果VB要支持Item,则必须要通过DISPID_VALUE

注意,虽然Next函数具有每次访问多个数据的能力,VB每次只访问一个数据

原创粉丝点击