簡體   English   中英

通過COM接口使用STL智能指針

[英]using STL smart pointers with COM interfaces

我正在嘗試將標准C ++庫智能指針與將MS COM用於其大部分功能的庫一起使用(我必須說,我對COM不熟悉)。 因此,我為我的unique_ptr使用了以下自定義刪除器

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 ++?

像這樣:

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之間的鏈接,並且IID_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
}

然后,我們重寫get接口函數:

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的查找功能和變量模板只是一種方法。

代碼未經測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM