Search code examples
c++directx-11wrl

Removing smart pointers


I'm testing some code examples for a CLR project. What would be this code equivalent without using smart pointers?

Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice;
...
m_d3dDevice.As(&dxgiDevice);

I tried something like this, but I'm not sure if it's ok.

ID3D11Device1* m_d3dDevice;
IDXGIDevice1* dxgiDevice;
...
dxgiDevice = reinterpret_cast<IDXGIDevice1*>(m_d3dDevice);

Solution

  • These are COM object pointers.

    I am not sure why you would not want to use a COM smart pointer template class. They eliminate most reference counting issues that can drive you crazy. And they have almost zero overhead.

    As such, you can use the ComPtr class or the legacy CComPtr from ATL as your smart ptr template type to automatically handle Addref, Release, and QueryInterface calls for yourself. You can also roll your own smart pointer classes, but ComPtr/CComPtr are very efficiently written.

    The rules of COM basically often break when you try to cast between interfaces without using QueryInterface. The actual concrete implementation is probably a C++ class with multiple inheritance from many interfaces. As such, casting between interfaces is probably a shift in the pointer value. But the compiler can't infer that from base class interfaces only. Also, many COM classes cheat this by having QueryInterface return an entirely different object.

    So, instead of this:

    dxgiDevice = reinterpret_cast<IDXGIDevice1*>(m_d3dDevice);
    

    This is probably all you need:

    HRESULT hr = m_d3dDevice->QueryInterface(&dxgiDevice);
    

    Some legacy SDKs don't have the template overload for IUnknown::QueryInterface that eliminates the need to deal with IID guids. So the full expanded function is really this:

    HRESULT hr = m_d3dDevice->QueryInterface(__uuidof(IDXGIDevice1), (void**)&dxgiDevice);
    

    Or the most "old school" way (assuming you know how to link in the definition for the IID variable). dxguids.lib might still be a thing, otherwise, the header file hacks for DEFINE_GUID.

    HRESULT hr = m_d3dDevice->QueryInterface(IID_IDXGIDevice1, (void**)&dxgiDevice);