對於COM調用,大量的AddRef/Release調用無疑是例行公事和讓人生厭。
_com_ptr_t 是vc運行庫中提供的固有的封裝COM接口的智能指針,相比CComPtr/CComQIPtr缺少移植性,
但是支持不是ATL實現部分的的異常和操作。
以下是DirectShow中播放一個文件的代碼:
IGraphBuilder *pGraph;
IMediaControl *pMediaControl;
IMediaEvent *pEvent;
// Create the filter graph manager and query for interfaces.
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change string to a file on your system.
pGraph->RenderFile(L"C://Example.avi", NULL);
// Run the graph.
pMediaControl->Run();
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Clean up.
pMediaControl->Release();
pEvent->Release();
pGraph->Release();
使用com_ptr_t後簡單了很多:
//這部分可以放到頭文件中
#include
_COM_SMARTPTR_TYPEDEF( IGraphBuilder , __uuidof(IGraphBuilder) );
_COM_SMARTPTR_TYPEDEF( IMediaControl , __uuidof(IMediaControl) );
_COM_SMARTPTR_TYPEDEF( IMediaEvent , __uuidof(IMediaEvent) );
...
IGraphBuilderPtr pGraph( CLSID_FilterGraph ) ;//調用CreateInstance
IMediaControlPtr pMediaControl = pGraph;//這裏會自動調用QueryInterface
IMediaEventPtr pEvent = pGraph;//這裏會自動調用QueryInterface
pGraph->RenderFile( L"L"C://Example.avi", NULL);
// Run the graph.
pMediaControl->Run();
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
//不需要調用Release()
假如我們要複製一個接口,常常要
pG1 = pG2;
pG1->AddRef();
...
pG1->Release();
對於_com_ptr_t , 只要pG1 = pG2;就可以了
注意以下的代碼:
IGraphBuilderPtr pGraph ;
pGraph.CreateInstance( CLSID_FilterGraph );
...
CoUninitialize();
因爲 pGraph 會在超出作用域時析構,也就是在CoUninitialize()之後調用 IUnkown::Release() ,這樣
會引起問題,可以這樣解決:
pGraph.Release(); CoUninitialize();
或者
pGraph = NULL; CoUninitialize(); //這樣會隱含的調用_com_ptr_t::Release()
絕對不可以調用pGraph->Release(); 因爲這是調用IUnkown::Release()然後再調用一次
pGraph.Release(); 將會兩次釋放接口指針。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/ljfxmf/archive/2008/06/04/2511029.aspx