How do I use _com_ptr_t?

2019-05-01 09:31发布

Say I have a class that owns a D3DDevice:

class Thing
{
public:
    Thing()
    {
        D3D11CreateDevice(..., &device, ...);
    }
    ~Thing()
    {
        device->Release();
    }
private:
    ID3D11Device* device;
};

From what I understand, I can use _com_ptr_t to ensure that the object gets deleted without my having to explicitly call Release() in the destructor. The problem though is that I can't figure out the correct syntax for the template.

I could find hardly any information on _com_ptr_t, and the closest thing I could find to an answer was this (Japanese) one. Following the syntax there, I get a bunch of compiler errors:

private:
    //ID3D11Device* device;
    _com_ptr_t <_com_IIID<ID3D11Device, &__uuidof(ID3D11Device)>> device;

error C2143: syntax error : missing ';' before '<'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2238: unexpected token(s) preceding ';'
error C2065: 'device' : undeclared identifier

By the way, I can use this to return COM pointers from functions and ensure that they get deleted when they leave the caller's scope, right?

标签: c++ com
3条回答
贪生不怕死
2楼-- · 2019-05-01 09:44

_com_ptr_t is for defining a smart pointer type. For example let's define the IHTMLDocument3Ptr type:

typedef _com_ptr_t <_com_IIID<IHTMLDocument3, &__uuidof(IHTMLDocument3)>> IHTMLDocument3Ptr;

There is this simple macro for that:

_COM_SMARTPTR_TYPEDEF(IHTMLDocument3, IID_IHTMLDocument3);

This creates IHTMLDocument3Ptr, a smart pointer:

IHTMLDocument3Ptr htmlDocument3;

Using CComQIPtr this would be defined as:

CComQIPtr<IHTMLDocument3> htmlDocument3;

There is the "comdefsp.h" file with predefined smart pointers for many COM interfaces (https://singularity.svn.codeplex.com/svn/base/Windows/Inc/comdefsp.h). The "comdef.h" file includes it automatically. For example a smart pointer for IDispatch is already defined:

IDispatchPtr dispatch;

Using CComPtr this would would be defined as:

CComPtr<IDispatch> dispatch;

_com_ptr_t = no ATL

The advantage of using _com_ptr_t over CComPtr/CComQIPtr is that you do not have to link to the ATL library.

Other smart COM pointers that do not require the ATL library are _bstr_t (equivalent of CComBSTR) and _variant_t (equivalent of CComVariant).

查看更多
We Are One
3楼-- · 2019-05-01 09:46

There are usually two ways of dealing with COM smart pointers that I would recommend:

1) You can #import the appropriate type library, which will auto generate smart pointer types based on _com_ptr_t.

2) You can use the CComPtr template to wrap your raw COM pointer in a smart pointer that takes care of the resource management via automatic AddRef/Release calls, but doesn't give you much else.

Because I'm a little lazy and normally I don't mind the implicit overhead of the wrapper auto-generated by #import, I usually use 1). One of the big benefits of using that approach is that the #import mechanism also generates function wrappers that make COM functions look more like normal functions with proper return types and a translation of the HRESULT to _com_error exception objects. IMHO that tends to improve the control flow in C++ COM code.

查看更多
Rolldiameter
4楼-- · 2019-05-01 09:56

The errors from the second code in your question mean that the compiler does not know one (or both) of the types before the <: you need to include the proper headers to ensure both _com_ptr_t and _com_IIID are valid and known types. Also, the >> might be parsed as "shift-right" operator, put a space between them to allow proper, portable parsing

comdef.h should fix both problems (see code listed)

查看更多
登录 后发表回答