DirectShowその2(CComPtr(ATL)導入)
C++的には、Com用のスマートポインタが是非とも必要だ。
調べたところ、CComPtrというものがATLに含まれることがわかった。
ATLはMFCと関係があるらしい?が、MFCは守備範囲外なので避けたいところだ・・・
で、WinDdkからMFC共々入手可能らしい。
- http://blogs.yahoo.co.jp/elku_simple/30240752.html
- http://ysmt.blog21.fc2.com/blog-entry-244.html
- http://d.hatena.ne.jp/sea-show/20100517/1274104239
CComPtrとCComQIPtrを使う
素晴らしくシンプルになった。
#include <tchar.h> #include <iostream> #include <string> #include <vector> #include <atlbase.h> #include <dshow.h> #pragma comment(lib, "strmiids") class Com { public: Com() { CoInitialize(NULL); } ~Com() { CoUninitialize(); } }; static std::wstring to_WideChar(UINT uCodePage, const std::string &text) { int size=MultiByteToWideChar(uCodePage, 0, text.c_str(), -1, NULL, 0); std::vector<wchar_t> buf(size); size=MultiByteToWideChar(uCodePage, 0, text.c_str(), -1, &buf[0], buf.size()); return std::wstring(buf.begin(), buf.begin()+size); } int main(int argc, char **argv) { if(argc<2){ std::cout << "usage: " << argv[0] << " {file}" << std::endl; return 0; } Com com; CComPtr<IGraphBuilder> gb; if(FAILED(gb.CoCreateInstance(CLSID_FilterGraph))){ return 1; } CComQIPtr<IMediaControl> mc(gb); if(!mc){ return 2; } std::wstring file=to_WideChar(CP_OEMCP, argv[1]); if(FAILED(gb->RenderFile(file.c_str(), NULL))){ return 3; } mc->Run(); std::cout << "hit any key" << std::endl; std::string line; std::getline(std::cin, line); return 0; }
CComPtrは
C:\WinDDK\7600.16385.1\inc\atl71\atlcomcli.h
に書いてあるので見てAddRef, Releaseの動きを把握する。
QueryInterfaceで取得するものは、CComQIPtrを使う。
classとIID_XXXXが一意に結びついているので
iidは__uuidof(class)で取得できるらしく、故に明示的に指定する必要が無いということですな。
リンク時に警告が出るw
ddkとvc2010のバージョンがあっていないとかか?
main.obj : warning LNK4254: セクション 'ATL' (50000040) は '.rdata' (40000040) に異なる属性を伴ってマージされています
問題なく動いたが、無視できる警告なのかは知らない