2017-02-27 1 views
1

나는 그 기능의 대부분에 대한 MS COM을 사용하는 라이브러리와 함께 표준 C + + 라이브러리 스마트 포인터를 사용하려고합니다 (나는 COM에 정통하지 않습니다). 로 대체 될 수COM 인터페이스와 STL 스마트 포인터를 사용하여

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

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

    IDeckLink * m_deckLink; 
}; 

이 : 그래서, 샘플 코드에서

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

unique_ptr

에 대해 다음 사용자 정의 Deleter가 있고, 우리가 뭔가를해야

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

Microsoft는 COM 포인터로 작업하기위한 몇 가지 스마트 포인터 클래스를 제공합니다. 그 중 하나를 사용하고 싶지 않은 이유가 있습니까? 이것은 존재하지 않는 문제에 대한 해답처럼 보입니다. –

+4

COM 용으로'CComPtr'을 사용할 것을 권장합니다. 비슷한 질문이 이미 SO에 있습니다 - [이 질문을 참조하십시오] (0120)를 참조하십시오. – 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, {}}; 
} 

우리 :

여기에 약간의 DRY 위반이
auto deckLink = upComInterface<IDeckLinkInput>(IID_IDeckLinkInput, deckLink); 

-이 작업을 수행 할 때마다 반복 될 수있다 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로 유형을 연결할 수 있습니다. IDeckLinkInput의 네임 스페이스에서이 작업을 수행 :

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); 

와 유형을 연결하는 방법에는 여러 가지가 있습니다를 특성 클래스를 포함한 guid. constexpr ADL 기반 조회 함수와 변수 템플릿은 한 가지 방법 일뿐입니다.

코드 테스트를 거치지 않았습니다.

+1

나는'CComPtr'을 사용하여 끝났지 만 이것은 알고있는 것이 좋다! – Luca

관련 문제