Я пытаюсь реализовать общую логику, используя агрегацию COM с ATL. Я определил базовый класс с именем CameraBase
, который доступен только через агрегацию. Поэтому я добавил аннотацию aggregateable
к его coclass
-объявлению.
[
uuid(...),
aggregatable
]
coclass CameraBase
{
[default] interface ICamera;
};
Я также добавил макрос DECLARE_ONLY_AGGREGATEABLE
в определение класса.
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()
...
}
Теперь у меня есть разные классы, которые где-то используют логику CameraBase
. Поэтому я расширил карту com родительского класса (например, SampleCamera
):
BEGIN_COM_MAP(CSampleCamera)
COM_INTERFACE_ENTRY_AGGREGATE(IID_ICamera, m_base)
...
END_COM_MAP
DECLARE_GET_CONTROLLING_UNKNOWN()
Поскольку я хочу иметь возможность вызывать членов CameraBase
(через интерфейс ICamera
) из родительского класса, я не хочу использовать COM_INTERFACE_ENTRY_AUTOAGGREGATE
, который хранит указатель внутреннего объекта как ссылку на IUnknown
. Поэтому я создаю его самостоятельно из FinalConstruct
-метода:
HRESULT FinalConstruct()
{
HRESULT hr;
if (FAILED(hr = m_camera.CoCreateInstance(CLSID_CameraBase, this->GetControllingUnknown(), CLSCTX_INPROC_SERVER)))
return hr;
}
Где m_camera
определяется как CComPtr<ICamera>
. Однако это приводит к ошибке CLASS_E_NOAGGREGATION
(HRESULT 0x80040110
). Мой текущий обходной путь состоит в том, чтобы сохранить две ссылки, IUnknown
и ICamera
, и запросить более позднюю.
if (FAILED(hr = m_base.CoCreateInstance(CLSID_CameraBase, this->GetControllingUnknown(), CLSCTX_INPROC_SERVER)) ||
FAILED(hr = m_base->QueryInterface(&m_camera)))
return hr;
Это работает, но выглядит немного странно, так как экземпляр класса (CameraBase
), для которого создается экземпляр, одинаков в обоих случаях. Я что-то упускаю? Правильно ли я использую внутренний объект? Почему возвращаемый указатель CoCreateInstance
должен иметь тип IUnknown
, если передается внешний неизвестный?
Заранее спасибо! :)