Problema com D3D & COM
-
23-09-2019 - |
Pergunta
Todas as interfaces D3D são derivadas da interface iunknown da COM, então eu, embora eu seguisse um caminho fácil para liberar objetos D3D e usar algo assim:
__inline BOOL SafeRelease(IUnknown*& pUnknown)
{
if(pUnknown != NULL && FAILED(pUnknown->Release()))
return FALSE;
pUnknown = NULL;
return TRUE;
}
Isso não funciona, pois o compilador gerará erros de conversão do tipo inválido, quando eu tento usá -lo. A única maneira de contornar isso que eu conseguia pensar era a seguinte:
__inline BOOL SafeRelease(void* pObject)
{
IUnknown* pUnknown = static_cast<IUnknown*>pObject;
if(pUnknown != NULL && FAILED(pUnknown->Release()))
return FALSE;
return TRUE;
}
Mas então eu perco alguma funcionalidade e também parece (e é) muito desonesto. Existe uma maneira melhor de fazer isso? Algo que funciona como o meu primeiro exemplo seria ideal, embora eu gostaria de evitar usar qualquer macros (se possível)
Solução
Uma função de modelo resolve seu problema:
template<class T>
__inline bool SafeRelease(T*& pUnknown)
{
if (pUnknown == NULL) return false;
if (0 == pUnknown->Release())
pUnknown = NULL;
return true;
}
Outras dicas
O caminho comum para lidar com recursos COM é empregar Raii e deixar aulas de auxiliar como o ATLS CComPtr
ou CComQIPtr
Lidar com a contagem de referência para você o máximo possível.
void f() {
CComPtr<IDirect3DDevice> sp3dDev;
getDevice(&sp3dDev);
// ... do stuff
} // smart pointer gets destroyed, calls Release() if valid
Se você pudesse fazer o que escreveu originalmente, violaria a segurança do tipo:
IDirect3DDevice *blah;
IUnknown *bar;
IUnknown *&unknown= blah;
unknown= bar;
Claramente, atribuindo bar
para unknown
significaria isso blah
aponta para um IUnknown
, que violaria a segurança do tipo.
Solução de Nobugz É provavelmente o que você deseja fazer, embora eu argumentasse que definir esses ponteiros como nulos não aumenta a qualidade do seu código. Se você precisar garantir que outro código não Release
Várias vezes, você provavelmente deve corrigir esse código em vez de fazer o código de buggy não falhar.
Eu não trabalho com o DirectX há algum tempo, mas lembro que tem um SAFE_RELEASE
Macro em algum lugar em seus cabeçalhos. A pesquisa de código do Google mostra que está em dxutil.h
.