2010-12-14 9 views
3

私はちょうどDirectShowプログラミングを始めていますが、DirectShow APIの 'C'性質は私のスキンクロールを行っています。無限の戻りコード、例外の代わりにaddref/release、ポインターへのポインタを取る関数...C++とDirectShow

DirectShowプログラミングの下にあるすべてのCOMの醜さを隠す「C++フレンドリーな」ラッパーはありますか?

答えて

5

DirectShowコードの98%の場合は、を使用しないでください。 AddRefまたはReleaseの呼び出しを参照してください。常にCComPtr <>を使用してください。このルールには少々の例外があります。

また、CCritSecとCAutoLockのようにロックを理解することが重要です。もう一度、CCritSecインスタンスを手動でロックするのは避けたいのですが、これはアプリケーションをデッドロックする良い方法です。

また、このコードはかなり便利なことができます:

#include <dxerr9.h> 

... 

HRESULT hr = S_OK; 

... something goes wrong ... 

CString err(::DXGetErrorString9(hr)); 
err += ::DXGetErrorDescription9(hr); 

最後に、あなたはDShowイベンティングを使用していることを確認してください。あらゆる種類の有用な情報がDShowグラフのイベントに含まれていますが、これが実装されていない(または間違って実装されている)アプリケーションがいくつあるのかは驚くべきことです。

これまでは、I wrote thisというDShowで作業するという落とし穴のいくつかをまとめました。悲しいことに、私はこれらの落とし穴を知っています。

+0

素晴らしい記事、BTW。ありがとう! – Roddy

-2

ラッパーが見つからない場合は、ブログエントリ"B true, or B thrown! (Using the >> throwing pattern)"で説明されているコーディングパターンのメリットがあります。

例そのブログのエントリ(これは簡単にCOMのために適合させることができ、実際に、私は最初のCOMの使用のためにそれを「発明」)から:

std::ostream& operator<<(std::ostream& stream, wchar_t const s[]) 
{ 
    Size const nBytes  = wcstombs(0, s, 0); 
    (nBytes >= 0) 
     || throwX("wcstombs failed to deduce buffer size"); 

    Size const    bufSize  = nBytes + 1; 
    std::vector<char>  buf(bufSize); 

    // The count of bytes written does not include terminating nullbyte. 
    wcstombs(&buf[0], s, bufSize) 
     >> Accept<IsNonNegative>() 
     || throwX("wcstombs failed to convert string"); 

    return (stream << &buf[0]); 
} 

ブログでいくつかの議論がありますが、明らかに誰もが持っています彼または彼女自身の好みの適切な演算子などのため、私はちょうど一般原則ここに投げている。

ああ、AddRefReleaseの代わりに、いくつかのCOMスマートポインタを使用してください。 ATL/MFCには非常に多くのものがあり(Visual C++では「組み込み」のものなど)、好きなものを選んで選択するだけです。たとえば、独自に作成します。 boost::intrusive_ptrに基づいています。

乾杯& HTH。、

+1

それぞれは自分のものですが、上記の構造は完全に理解できないものです。それは一目で何がやっているのか、それほど明白ではありません。 – Goz

+0

@Goz:複数のプログラミング言語(PerlやPythonなど)での経験があることを助けます。 –

+1

@Alf:私は「IMO、それは悪いC++プログラミング構造です」という言葉を最後の数語に置き換えます。 – Goz

4

CComPtrはかなり便利なものです、

を越えてあなただけのHRESULTSのようなものと一緒に暮らす必要があります。私はむしろ例外的にそれらを好む...彼ら自身でそれぞれ...と働くことをずっと容易に見つける。

2

DirectShowがquartz.dll、DirectShow編集サービスがqedit.dllに実装されていることは知っておく価値があります。

Visual C++のCompiler COM Supportでこれらの2つを使用して、DirectShowクライアントアプリケーションに書き込むことができます。

ここでは、小さな再生media_fileの例を示します(cl/D_UNICODE playfileでコンパイルします)。cpp):

#include <iostream> 

#import <quartz.dll> rename_namespace("dshow") 
#import <qedit.dll> rename_namespace("dshow") 

// Required for CLSID_FilterGraph 
#include <uuids.h> 
#pragma comment(lib, "strmiids.lib") 

int wmain(int argc, wchar_t* argv[]) 
{ 
    using namespace dshow; 
    using namespace std; 

    if (argc != 2) 
    { 
     wcout << "Usage: play media_file" << endl; 
     return 1; 
    } 

    struct ComInitializer 
    { 
     ComInitializer() 
     { 
      ::CoInitialize(0); 
     } 

     ~ComInitializer() 
     { 
      ::CoUninitialize(); 
     } 
    } comInit; 

    try 
    { 
     IGraphBuilderPtr graphBuilder; 
     graphBuilder.CreateInstance(CLSID_FilterGraph); 

     graphBuilder->RenderFile(argv[1], 0); 

     IMediaControlPtr mediaControl = graphBuilder; 
     mediaControl->Run(); 

     wcout << "Press Return to stop playback." << endl; 
     wcin.get(); 

     mediaControl->Stop(); 
    } 
    catch (const _com_error& err) 
    { 
     wcout << L"Error code: 0x" << hex << err.Error() << endl; 
    } 
} 

この方法をコンソールDirectShow oggencアプリケーションの構築に使用しました。

+0

これがDirectShowのドキュメントやその他のオンラインサンプルで使用されていない理由についての手掛かりはありますか? MSXMLドキュメントには、これらの自動生成されたスマートポインタを使用する方法について説明した別のセクションがあります。 –

+0

おそらく彼らはこれについて知りません。ドキュメンテーションと本は、非常にCスタイルのものです。このスタイルはDirectShow.NETによく似ています。 –