#cpp #com #directx
Делаю обертку над некоторыми из объектов DirectX, дошло дело до копирования из другого объекта DirectX т.е. преобразование из DirectX объекта в объект моего типа. У каждого из таких объектов есть метод QueryInterface, далее, я запрашиваю интересующий меня интерфейс у данного объекта и провожу некоторые действия с ним. По моему мнению другой объект из которого был создан объект у которого я запросил интерфейс, кол-во ссылок должно увеличиться, и для предотвращения утечек памяти, я должен вызвать Release для объекта который я запросил. Правильно ли так делать, и вообще нужно ли? HRESULT result = ptr->QueryInterface(__uuidof(ID2D1HwndRenderTarget), reinterpret_cast(&m_render_target_)); if(result != S_OK) { throw std::exception("Failed to QueryInterface from ID2D1SolidColorBrush"); } result = m_render_target_->CreateSolidColorBrush(ptr->GetColor(), &m_solid_color_brush_ptr_); if (result != S_OK) { throw std::exception("Failed to CreateSolidColorBrush from ID2D1HwndRenderTarget"); } m_solid_color_brush_ptr_->SetOpacity(ptr->GetOpacity()); D2D1_MATRIX_3X2_F matrix; memset(&matrix, 0, sizeof matrix); ptr->GetTransform(&matrix); m_solid_color_brush_ptr_->SetTransform(matrix); Для m_render_target_ локального поля, я должен вызвать Release в деструкторе, а в обычном конструкторе добавить ссылку вызвав AddRef, т.к. в обычный конструктор передается указатель на этот объект?
Ответы
Ответ 1
Да, вызов QueryInterface увеличивает внутренний счетчик ссылок объекта, поэтому у успешно полученного указателя следует вызвать Release. Однако делать это все руками не следует, благо это все уже реализовано в умных указателях, например WRL::ComPtr: ::Microsoft::WRL::ComPtr<::ID3D11Device> p_d3d_device{}; // создаем D3D устройство... ::Microsoft::WRL::ComPtr<::IDXGIDevice> p_dxgi_device{}; if(!SUCCEEDED(p_d3d_device.As(&p_dxgi_device))) // тут вызовется `QueryInterface` { /* обработка ошибки */ } // при выходе из области видимости у каждого указателя будет вызван `Release`Ответ 2
Правило очень простое, AddRef и Release должны быть строго симметричны. И да, корректный QueryInterface в случае успеха, должен вызывать AddRef для объекта. Поэтому после завершения работы с вашими интерфейсами, вы должны вызвать Release и все. Офтоп. Второе исключение которое вы бросаете выглядит опасно, не забыли ли вы что m_render_target уже получен и нуждается в заботе.
Комментариев нет:
Отправить комментарий