2010-02-28 45 views
1

所有的D3D接口從COM的IUnknown接口派生的,所以我雖然我會採取一種簡單的途徑釋放D3D對象,並使用這樣的事:問題的D3D和COM

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

    pUnknown = NULL; 
    return TRUE; 
} 

這不盡管如此,因爲當我嘗試使用它時,編譯器會生成無效的類型轉換錯誤。圍繞它的唯一途徑我能想到的是這樣的:

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

    return TRUE; 
} 

但後來我失去了一些功能,並且它看起來也(是)非常狡猾。有一個更好的方法嗎?一些作品就像我的第一個例子將是最佳的,但我想避免使用任何宏(如果可能)

回答

3

的模板功能可以解決你的問題:

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

問題中的代碼和此響應中的代碼不正確。 IUnknown :: Release()返回一個ULONG,而不是一個HRESULT。 ULONG通常是對象的重新計數。它不是Release()是成功還是失敗的指標。 請參閱IUnknown :: Release()文檔,地址爲http://msdn.microsoft.com/en-us/library/ms682317(VS.85).aspx – Ants

+0

@ants:我只是在處理WinError中的註釋。 h: '// COM函數和方法的返回值是一個HRESULT.' 猜測那麼這就解決了,那麼也謝謝你指出:) – Necrolis

0

如果你能最初做你寫的,那麼你就違反類型安全:

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

顯然,分配barunknown將意味着blah指向一個IUnknown,這將違反類型安全。

nobugz's solution可能是你想要做的,雖然我會爭辯說,將這些指針設置爲NULL並不會增加代碼的質量。如果您需要確保其他代碼不會Release多次,那麼您可能應該修復該代碼,而不是讓錯誤的代碼不會失敗。

+0

我看到它會導致問題,但我越來越甚至在將一個IDirect3DDevice *轉換爲一個IUnknown *時都會出現問題,這應該起作用 – Necrolis

+0

您正在投射到IUnknown *&,它是對IUnknown指針的引用。看看SafeRelease的簽名。 – MSN

0

我有一段時間沒有使用過DirectX,但是我記得它有一個SAFE_RELEASE宏的頭文件。谷歌代碼搜索顯示它在dxutil.h

+0

我想避免使用宏的幾個原因,其中一個是我無法檢查發佈是否成功,但當我搜索「SafeRelease D3D COM」時,我沒有任何用處 – Necrolis

4

處理COM資源的常用路徑是使用RAII,並讓助手類像ATL CComPtrCComQIPtr儘可能地爲您處理引用計數。

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