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

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每次只访问一个数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值