CComPtr и CComQIPtr
От: Nine  
Дата: 21.05.04 19:36
Оценка:
Всем привет!.
Если кто знает подскажите чем отличаются CComPtr и CComQIPtr?

И что за жуть здесь написана:
CComPtr< IGraphBuilder > m_pGraph;
CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = m_pGraph;
Re: CComPtr и CComQIPtr
От: retalik www.airbandits.com/
Дата: 21.05.04 20:21
Оценка:
Здравствуйте, Nine, Вы писали:

N>Всем привет!.

N>Если кто знает подскажите чем отличаются CComPtr и CComQIPtr?

Перед тем как отправить сообщение в форум, рекомендуется нажать кнопку "Найти ответ" — по этой теме выводится 96 ссылок.
Ну да ладно. CComQIPtr выполняет неявный вызов QueryInterface при присваивании интерфейсу другого типа.

N>И что за жуть здесь написана:

N>CComPtr< IGraphBuilder > m_pGraph;
N>CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = m_pGraph;
Аналог:
CComPtr< IGraphBuilder > m_pGraph;
CComPtr< IVideoWindow> pWindow;
if(FAILED(m_pGraph->QueryInterface(&pWindow)) // CComPtr::QueryInterface типизирован, IID не требуется
  pWindow = 0;
Успехов,
Виталий.
Re[2]: CComPtr и CComQIPtr
От: Nine  
Дата: 22.05.04 10:55
Оценка:
Здравствуйте, retalik.

Спасибо за ответ. Многое прояснилось сразу и кое что прямо сейчас Возникает встречный вопрос.
Два вопроса.
1.Является ли сл. код аналогом предыдущего:

-----------------------------------------------
IGraphBuilder * m_pGraph;
IVideoWindow * pWindow;

CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IGraphBuilder, (void **) &pGraph);
m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &pWindow);

-----------------------------------------------
2.В вашем ответе, разве m_pGraph не нужно создавать ф-ей CoCreateInstance???

CComPtr< IGraphBuilder > m_pGraph;
CComPtr< IVideoWindow> pWindow;
if(FAILED(m_pGraph->QueryInterface(&pWindow))
pWindow = 0;


P.S.
И еще, раз такая пьянка пошла:
у меня есть MSDN, но никака не могу найти сколь более обширной статьи по использованию этих двух классов.
Если знаете — подскажите. А если нет, то еще вопрос:

CComPtr< ISampleGrabber > m_pGrabber;

m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );//???
//я так понимаю, что m_pGrabber передается конструктору в кач. параметра, но что это означает я так и не нашел.


Спасибо за помощь
Re[3]: CComPtr и CComQIPtr
От: retalik www.airbandits.com/
Дата: 22.05.04 12:44
Оценка: 11 (2)
Здравствуйте, Nine, Вы писали:

N>1.Является ли сл. код аналогом предыдущего:


N>-----------------------------------------------

N>IGraphBuilder * m_pGraph;
N>IVideoWindow * pWindow;

N>CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IGraphBuilder, (void **) &pGraph);

N>m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &pWindow);
N>-----------------------------------------------
Почти является. Существенная разница: при выходе из области видимости классы CComPtr CComQIPtr сами вызовут Release(), а в данном примере нужно не забыть сделать это самостоятельно.
Кстати, если уж мы о DirectShow, маленький оффтопик: рекомендую установить DirectX Debug Runtime — при завершении программы будет выдаваться предупреждение обо всех "неубитых" объектах.

Еще одно замечание: в этом форуме есть тэги для оформления кода — с ними читать код гораздо удобнее.

N>2.В вашем ответе, разве m_pGraph не нужно создавать ф-ей CoCreateInstance???


N>CComPtr< IGraphBuilder > m_pGraph;

N>CComPtr< IVideoWindow> pWindow;
N>if(FAILED(m_pGraph->QueryInterface(&pWindow))
N> pWindow = 0;
Как-то создавать, конечно, нужно. Я привел эквивалент для данного кусочка:
CComPtr< IGraphBuilder > m_pGraph;
CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = m_pGraph;

, в котором тоже не было создания. Кстати, у классов *Ptr есть более удобный метод CoCreateInstance(), пользоваться рекомендуется им.

N>CComPtr< ISampleGrabber > m_pGrabber;

N>m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
N>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );//???
N>//я так понимаю, что m_pGrabber передается конструктору в кач. параметра, но что это означает я так и не нашел.
То же самое. Создается "умный указатель" на интерфейс IBaseFilter путем вызова QueryInterface в конструкторе CComQIPtr.
Успехов,
Виталий.
Re[4]: CComPtr и CComQIPtr
От: Nine  
Дата: 22.05.04 16:09
Оценка:
Здравствуйте, retalik, Вы писали:


N>>CComPtr< ISampleGrabber > m_pGrabber;

N>>m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
N>>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );//???
N>>//я так понимаю, что m_pGrabber передается конструктору в кач. параметра, но что это означает я так и не нашел.
R>То же самое. Создается "умный указатель" на интерфейс IBaseFilter путем вызова QueryInterface в конструкторе CComQIPtr.

Так что жеж, это всего лишь прихоть использовать
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
вместо
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;

P.S.
Спасибо за ответы. Постепенно начинаю втыкать. не мучал бы вопросами, но поиск на сайте пока не работает,
а ждать нет времени.

Nine
Re[5]: CComPtr и CComQIPtr
От: rus blood Россия  
Дата: 22.05.04 16:31
Оценка:
N>Так что жеж, это всего лишь прихоть использовать
N>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
N>вместо
N>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;

Запись
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
и
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
эквивалетнты.

В обоих случаях будет вызван конструктор с параметром.
Имею скафандр — готов путешествовать!
Re[6]: CComPtr и CComQIPtr
От: retalik www.airbandits.com/
Дата: 22.05.04 16:48
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Запись
RB>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
RB>
и
RB>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
RB>
эквивалетнты.

RB>В обоих случаях будет вызван конструктор с параметром.

Последнее уточнение, хотя это уже относится к языку C++. В данном случае, эти две записи действительно эквивалентны — это две формы вызова конструктора. Но небольшая разница между ними все-таки есть. Если бы конструктор CComQIPtr был объявлен с ключевым словом explicit, второе выражение бы не скомпилировалось.
Успехов,
Виталий.
Re[7]: CComPtr и CComQIPtr
От: v0id  
Дата: 23.05.04 07:05
Оценка: -3
Здравствуйте, retalik, Вы писали:

R>Здравствуйте, rus blood, Вы писали:


RB>>Запись
RB>>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
RB>>
и
RB>>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
RB>>
эквивалетнты.

RB>>В обоих случаях будет вызван конструктор с параметром.

R>Последнее уточнение, хотя это уже относится к языку C++. В данном случае, эти две записи действительно эквивалентны — это две формы вызова конструктора. Но небольшая разница между ними все-таки есть. Если бы конструктор CComQIPtr был объявлен с ключевым словом explicit, второе выражение бы не скомпилировалось.

Раз уж пошли учточнения , то

CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );


просто напросто вызывает конструктор копирования, а

CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;


-опрация присваивания()
и еще есть огромный недостаток у этого умного указателя- Release() там открытый,т.е. может случится так что уничтоженный объект вручную будет убиваться в деструкторе
Re[8]: CComPtr и CComQIPtr
От: retalik www.airbandits.com/
Дата: 23.05.04 10:43
Оценка: 12 (2)
Здравствуйте, v0id, Вы писали:

Налицо несколько грубейших ошибок — придется опять вмешаться.

V>Раз уж пошли учточнения , то

V>
V>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
V>

V> просто напросто вызывает конструктор копирования, а
Ошибка. Не конструктор копирования, а конструктор вообще, так как m_pGrabber не является эквивалентным типом для CComQIPtr< IBaseFilter >. На этом и построен принцип CComQIPtr — в конструкторе с указателем на другой интерфейс вызвать QueryInterface.
Вот как реализован конструктор копирования:
CComQIPtr(const CComQIPtr<T,piid>& lp) throw() :
  CComPtr<T>(lp.p)
{
}

То есть, сохраняем указатель (вызываем Addref в конструкторе CComPtr) и больше ничего не делаем.
А вот использованный нами контруктор:
CComQIPtr(IUnknown* lp) throw()
{
  if (lp != NULL)
    lp->QueryInterface(*piid, (void **)&p);
}

Разница видна невооруженным глазом.

V>
V>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
V>

V> -опрация присваивания()
Ошибка! Это другой синтаксис вызова конструктора. Вот из-за того, что такую форму конструктора часто путают с операцией присваивания, и ввели дополнительное ключевое слово explicit. При описании конструктора с этим спецификатором его нельзя будет вызывать в таком виде, о чем я и говорил в предыдущем сообщении.

V>и еще есть огромный недостаток у этого умного указателя- Release() там открытый,т.е. может случится так что уничтоженный объект вручную будет убиваться в деструкторе

Ошибка! Эти классы в operator-> возвращают не "голый" интерфейс, а специальный класс
template <class T>
class _NoAddRefReleaseOnCComPtr : public T
{
  private:
   STDMETHOD_(ULONG, AddRef)()=0;
   STDMETHOD_(ULONG, Release)()=0;
};

В котором два этих метода закрыты. То есть вы не сможете вызвать Release() так:
pGrabBase->Release();

Ну а то, что у них есть служебный метод Release, так это по необходимости. Вдруг придется явно управлять временем жизни объекта. И если в деструкторе кто-то "по ошибке" употребит такую форму:
pGrabBase.Release();

, то он сам себе злобный буратина.
Успехов,
Виталий.
Re[9]: CComPtr и CComQIPtr
От: v0id  
Дата: 23.05.04 13:23
Оценка:
Здравствуйте, retalik, Вы писали:

R>Здравствуйте, v0id, Вы писали:


R>Налицо несколько грубейших ошибок — придется опять вмешаться.


V>>Раз уж пошли учточнения , то

V>>
V>>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
V>>

V>> просто напросто вызывает конструктор копирования, а
R>Ошибка. Не конструктор копирования, а конструктор вообще, так как m_pGrabber не является эквивалентным типом для CComQIPtr< IBaseFilter >. На этом и построен принцип CComQIPtr — в конструкторе с указателем на другой интерфейс вызвать QueryInterface.
R>Вот как реализован конструктор копирования:
R>
R>CComQIPtr(const CComQIPtr<T,piid>& lp) throw() :
R>  CComPtr<T>(lp.p)
R>{
R>}
R>

R>То есть, сохраняем указатель (вызываем Addref в конструкторе CComPtr) и больше ничего не делаем.
R>А вот использованный нами контруктор:
R>
R>CComQIPtr(IUnknown* lp) throw()
R>{
R>  if (lp != NULL)
    lp->>QueryInterface(*piid, (void **)&p);
R>}
R>

R>Разница видна невооруженным глазом.

..да поторопился(надо было глянуть не его описание)
V>>
V>>CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;
V>>

V>> -опрация присваивания()
R>Ошибка! Это другой синтаксис вызова конструктора. Вот из-за того, что такую форму конструктора часто путают с операцией присваивания, и ввели дополнительное ключевое слово explicit. При описании конструктора с этим спецификатором его нельзя будет вызывать в таком виде, о чем я и говорил в предыдущем сообщении.
Если оператор не определен, то согласен
V>>и еще есть огромный недостаток у этого умного указателя- Release() там открытый,т.е. может случится так что уничтоженный объект вручную будет убиваться в деструкторе
R>Ошибка! Эти классы в operator-> возвращают не "голый" интерфейс, а специальный класс
R>
R>template <class T>
R>class _NoAddRefReleaseOnCComPtr : public T
R>{
R>  private:
R>   STDMETHOD_(ULONG, AddRef)()=0;
R>   STDMETHOD_(ULONG, Release)()=0;
R>};
R>

R>В котором два этих метода закрыты. То есть вы не сможете вызвать Release() так:
R>
R>pGrabBase->Release();
R>

R>Ну а то, что у них есть служебный метод Release, так это по необходимости. Вдруг придется явно управлять временем жизни объекта. И если в деструкторе кто-то "по ошибке" употребит такую форму:
R>
R>pGrabBase.Release();
R>

R>, то он сам себе злобный буратина.
Не понял, что подразумевается под словом служебный.Пример можете привести с управлением жизни объекта?
Re[10]: CComPtr и CComQIPtr
От: retalik www.airbandits.com/
Дата: 23.05.04 13:39
Оценка:
Здравствуйте, v0id, Вы писали:

А можно так жутко не оверквотить? А то похоже на неуважение к другим посетителям — вынуждены продираться через километры цитат, чтобы найти две строчки ответа...

R>>Ошибка! Это другой синтаксис вызова конструктора. Вот из-за того, что такую форму конструктора часто путают с операцией присваивания, и ввели дополнительное ключевое слово explicit. При описании конструктора с этим спецификатором его нельзя будет вызывать в таком виде, о чем я и говорил в предыдущем сообщении.

V>Если оператор не определен, то согласен

Никаких "если"! Вот вызов конструктора:
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase = m_pGrabber;

А вот — вызов оператора присваивания:
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase;
pGrabBase = m_pGrabber;

Программируя на C++, эту разницу нужно понимать четко. Если есть сомнения — задай вопрос в форуме C++.

V>Не понял, что подразумевается под словом служебный.Пример можете привести с управлением жизни объекта?

Ну такое иногда случается — например, при смешивании кода с использованием "умных указателей" и кода, написанного без учета соглашений COM. Допустим, мы сохраняем CComPtr в контейнере, который хранит "голые" интерфейсные указатели, но не вызывает AddRef — нужно увеличить счетчик ссылок самостоятельно.
Успехов,
Виталий.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.