DirectShowその2(CComPtr(ATL)導入)

C++的には、Com用のスマートポインタが是非とも必要だ。
調べたところ、CComPtrというものがATLに含まれることがわかった。
ATLはMFCと関係があるらしい?が、MFCは守備範囲外なので避けたいところだ・・・


で、WinDdkからMFC共々入手可能らしい。

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) に異なる属性を伴ってマージされています

問題なく動いたが、無視できる警告なのかは知らない