2010-02-28 7 views
1

toutes les interfaces D3D sont dérivées de l'interface IUnknown COM, donc je pensais que je prendrais un itinéraire facile pour libérer des objets D3D et utiliser quelque chose comme ceci:problème D3D & COM

__inline BOOL SafeRelease(IUnknown*& pUnknown) 
{ 
    if(pUnknown != NULL && FAILED(pUnknown->Release())) 
     return FALSE; 

    pUnknown = NULL; 
    return TRUE; 
} 

cela ne fonctionne bien, car le compilateur va générer des erreurs de conversion de type non valide, lorsque j'essaie de l'utiliser. la seule façon autour d'elle que je pouvais penser était le suivant:

__inline BOOL SafeRelease(void* pObject) 
{ 
    IUnknown* pUnknown = static_cast<IUnknown*>pObject; 
    if(pUnknown != NULL && FAILED(pUnknown->Release())) 
     return FALSE; 

    return TRUE; 
} 

mais je lâche certaines fonctionnalités et il semble aussi (et est) très douteux. Y a-t-il une meilleure manière de faire cela? quelque chose qui fonctionne comme mon premier exemple serait optimale, bien que je voudrais éviter d'utiliser des macros (si son possible)

Répondre

3

Une fonction de modèle résout votre problème:

template<class T> 
__inline bool SafeRelease(T*& pUnknown) 
{ 
    if (pUnknown == NULL) return false; 
    if (0 == pUnknown->Release()) 
     pUnknown = NULL; 
    return true; 
} 
+4

Le code dans la question et dans cette réponse est incorrect. IUnknown :: Release() renvoie un ULONG, pas un HRESULT. Le ULONG est généralement le refcount de l'objet. Ce n'est pas un indicateur de savoir si le Release() a réussi ou échoué. Voir la documentation IUnknown :: Release() à l'adresse http://msdn.microsoft.com/en-us/library/ms682317(VS.85).aspx – Ants

+0

@ants: Je suivais simplement les commentaires dans WinError. h: '// La valeur de retour des fonctions COM et des méthodes est un HRESULT. ' devinez alors cela est corrigé alors aussi, merci de le signaler :) – Necrolis

0

Si vous pouvez faire ce que vous avez initialement REDIGES alors vous violer la sécurité de type:

IDirect3DDevice *blah; 
IUnknown *bar; 
IUnknown *&unknown= blah; 
unknown= bar; 

Il est clair que l'attribution bar-unknown signifierait que blah pointe vers un IUnknown, ce qui serait contraire à la sécurité de type.

nobugz's solution est probablement ce que vous voulez faire, même si je dirais que la définition de ces pointeurs à NULL n'augmente pas la qualité de votre code. Si vous devez vous assurer que les autres codes ne seront pas Release plusieurs fois, vous devriez probablement corriger ce code plutôt que de faire du code bogué.

+0

Je vois où cela causerait un problème, mais je recevais problèmes même en jetant un IDirect3DDevice * à un IUnknown *, ce qui devrait fonctionner – Necrolis

+0

Vous avez lancé la commande IUnknown * &, qui est une référence à un pointeur de IUnknown. Regardez la signature de SafeRelease. – MSN

0

Je n'ai pas travaillé avec DirectX depuis un moment mais je me souviens qu'il a une macro SAFE_RELEASE quelque part dans ses en-têtes. La recherche de code Google montre que c'est au dxutil.h.

+0

Je voulais éviter d'utiliser des macros pour quelques raisons, l'une étant que je ne peux pas vérifier si la version réussit, mais quand j'ai googlé "SafeRelease D3D COM" je n'ai rien d'utile – Necrolis

4

La route couramment utilisée pour traiter les ressources COM consiste à utiliser RAII et à laisser des classes auxiliaires telles que les ATL CComPtr ou CComQIPtr gérer le comptage de références pour vous autant que possible.

void f() { 
    CComPtr<IDirect3DDevice> sp3dDev; 
    getDevice(&sp3dDev); 
    // ... do stuff 
} // smart pointer gets destroyed, calls Release() if valid