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?
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.
_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
).
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)