2017-02-27 12 views
1

私は、その機能のほとんどにMS COMを使用するライブラリで標準のC++ライブラリスマートポインタを使用しようとしています(COMに精通していないと言う必要があります)。だから、私は、サンプルコードでは、私のunique_ptrCOMインターフェイスでSTLスマートポインタを使用する

struct COMDeleter { 
    template<typename T> void operator()(T* ptr) { 
     if (ptr) ptr->Release(); 
    } 
}; 

ための次のカスタム削除手段を持って、私たちのようなものを持っている:

class MyClass 
{ 
public: 
    MyClass(IDeckLink * device) 
     : m_deckLink(device) 
    {    
    } 

    MyClass::~MyClass() 
    { 
     if (m_deckLink != NULL) 
     { 
      m_deckLink->Release(); 
      m_deckLink = NULL; 
     } 
    } 

    IDeckLink * m_deckLink; 
}; 

これを置き換えることができます。

class MyClass 
{ 
public: 
    MyClass(IDeckLink * device) 
    { 
     m_deckLink.reset(device); 
    } 
    std::unique_ptr<IDeckLink, COMDeleter> m_deckLink; 
}; 

、私はIDeckLinkInputと呼ばれる別のインターフェイスを持っていますが、これは同様の方法で折り返していますが、これが初期化される方法は次のように異なります。

IDeckLinkInput* m_deckLinkInput = NULL; 
if (m_deckLink->QueryInterface(IID_IDeckLinkInput, (void**) &m_deckLinkInput) != S_OK) 
     return false; 

だから、私のようなスマートポインタがある場合:私は、私は上記のような初期化機能でそれを使用する方法を確認していない

std::unique_ptr<IDeckLinkInput, COMDeleter> m_deckLinkInput(nullptr); 

を?私は古いスタイルのC++に固執する必要がありますか?このような

+5

マイクロソフトでは、COMポインタを操作するためのスマートポインタクラスをいくつか提供しています。その中の1つを使用したくない理由はありますか?これは存在しない問題の解決策のようです。 –

+4

COM用に 'CComPtr'を使うことをお勧めします。同様の質問はすでにSOにあります - [この質問を参照](http://stackoverflow.com/questions/21820301/using-stdunique-ptr-for-managing-com-objects) – mpiatek

+0

ありがとう!申し訳ありませんが、CComPtrを認識していませんでした。それを見ていたはずです。 COMを使用し始めたばかりです... – Luca

答えて

2

何か:

template<class U, class T> 
std::unique_ptr<U, COMDeleter> 
upComInterface(GUID guid, T const& src) { 
    if (!src) return {}; 
    T* r = nullptr; 
    if (src->QueryInterface(guid, (void**)&r) != S_OK) 
    return {}; 
    return {r, {}}; 
} 

その後、我々は:

auto deckLink = upComInterface<IDeckLinkInput>(IID_IDeckLinkInput, deckLink); 

マイナーDRY違反がここにあります - IDeckLinkInputIID_IDeckLinkInputの間のリンクは、あなたがこれを行うたびに繰り返さなければならず、間違っていると、未定義の動作につながります。

これはいくつかのメカニズムで解決できます。個人的に、私は、タグディスパッチタイプでいいと思う:

namespace MyComHelpers { 
    template<class T> struct com_tag_t {using type=T; constexpr com_tag_t(){};}; 
    template<class T> constexpr com_tag_t<T> com_tag{}; 

    template<class T> 
    constexpr void get_com_guid(com_tag_t<T>) = delete; // overload this for your particular types 

    template<class T> 
    constexpr GUID interface_guid = get_com_guid(com_tag<T>); 
} 

今、私たちは、GUIDを持つタイプを関連付けることができます。私たちは、その後GETインタフェース機能を書き換える

constexpr GUID get_com_guid(MyComHelpers::com_tag_t<IDeckLinkInput>) { 
    // constexpr code that returns the GUID 
} 

std::unique_ptr<U, COMDeleter> 
com_cast(T const& src) { 
    if (!src) return {}; 
    T* r = nullptr; 
    if (src->QueryInterface(MyComHelpers::interface_guid<T>, (void**)&r) != S_OK) 
    return {}; 
    return {r, {}}; 
} 

及び使用は次のようになります。

auto declLink = com_cast<IDeckLinkInput>(m_deckLinkInput); 

とタイプを関連付けるには、多くの方法がありますIDeckLinkInputの名前空間では、これを行いますtraidクラスを含むguid。 constexpr ADLベースのルックアップ関数と変数テンプレートは単なる1つの方法です。

コードはテストされていません。

+1

私は 'CComPtr'を使い終わったが、これは知っておいてよかった! – Luca

関連する問題