I am trying to implement shared logic using COM aggregation with ATL. I've defined a base class, called CameraBase
, that is only available through aggregation. Therefor I've added the aggregateable
annotation to it's coclass
-declaration.
[
uuid(...),
aggregatable
]
coclass CameraBase
{
[default] interface ICamera;
};
I've also added the DECLARE_ONLY_AGGREGATEABLE
macro to the class definition.
class ATL_NO_VTABLE CCameraBase :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CCameraBase, &CLSID_CameraBase>,
public ISupportErrorInfo,
public IProvideClassInfoImpl<...>,
public IDispatchImpl<...>
{
public:
CCameraBase()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_CAMERABASE)
DECLARE_ONLY_AGGREGATABLE(CCameraBase)
BEGIN_COM_MAP(CCameraBase)
...
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
...
}
Now I have different classes who are using the logic of CameraBase
somewhere. Therefor I've extented the com map of the parent class (e.g. SampleCamera
):
BEGIN_COM_MAP(CSampleCamera)
COM_INTERFACE_ENTRY_AGGREGATE(IID_ICamera, m_base)
...
END_COM_MAP
DECLARE_GET_CONTROLLING_UNKNOWN()
Since I want to be able to call the members on CameraBase
(through the ICamera
interface) from the parent class, I do not want to use COM_INTERFACE_ENTRY_AUTOAGGREGATE
, which stores the inner object's pointer as a reference of IUnknown
. Therefor I am creating it on my own from the FinalConstruct
-method:
HRESULT FinalConstruct()
{
HRESULT hr;
if (FAILED(hr = m_camera.CoCreateInstance(CLSID_CameraBase, this->GetControllingUnknown(), CLSCTX_INPROC_SERVER)))
return hr;
}
Where m_camera
is defined as CComPtr<ICamera>
. However, this does result in a error CLASS_E_NOAGGREGATION
(HRESULT 0x80040110
). My current workaround is to store two references, IUnknown
and ICamera
, and query for the later one.
if (FAILED(hr = m_base.CoCreateInstance(CLSID_CameraBase, this->GetControllingUnknown(), CLSCTX_INPROC_SERVER)) ||
FAILED(hr = m_base->QueryInterface(&m_camera)))
return hr;
This works, but it feels kinda strange, since the class (CameraBase
) that get's instanciated is the same in both cases. Am I missing something? Am I using the right way to aggregate the inner object? Why does the returned pointer of CoCreateInstance
need to be of type IUnknown
, if an outer unknown is passed?
Thanks in advance! :)