使用c++封装com的IEnum接口
最近在做DirectShow的一些开发,其中总要用到连接filter之类的操作,而filter是通过com中的枚举器得到的。在c++中使用枚举器十分不方便,可以看下一段代码:
HRESULT hr = pGraph->EnumFilters(&pEnum);
if (FAILED(hr)) return result;
while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
{
FILTER_INFO FilterInfo;
hr = pFilter->QueryFilterInfo(&FilterInfo);
if (FAILED(hr))
{
MessageBox(NULL, TEXT("Could not get the filter info"),
TEXT("Error"), MB_OK | MB_ICONERROR);
continue; // Maybe the next one will work.
}
}
pEnum->Release();
如果每天都要写这样的代码,真的要晕倒,想想c++中不时有iterator吗,而且我也经常用iterator,我用iterator可比Ienum要熟得多。在c++中,想做什么可都是你自己的事,那就做一个iterator adapter吧,然后我就不用写循环了,用for_each就可以搞定了。
先分析一下,IEnum中主要方法是Next、Reset,这样看来应该是个forward_iterator,不过大多数stl算法已经足够了。好吧,先写一个,不过还是要看看书,找了TCPL看看,forward iterator要实现 =*p , -> , *p= , ++ , == != 这些操作符。如下代码:
struct graph_filter_iterator :
public std::iterator<std::forward_iterator_tag,
IBaseFilter*,
ptrdiff_t,
IBaseFilter*,
IBaseFilter*>
{
public:
explicit graph_filter_iterator()
{}
explicit graph_filter_iterator(IEnumFilters* penum)
{
pEnum = penum;
reset();
}
IBaseFilter* operator*() const
{
return pFilter.p;
}
IBaseFilter* operator->()const
{
return pFilter.p;