首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将DirectX接口转换为IUnknown指针

将DirectX接口转换为IUnknown指针
EN

Stack Overflow用户
提问于 2013-02-04 21:43:54
回答 3查看 825关注 0票数 1

在我的代码中有相当多的接口,我想将重复的Release代码封装在另一种方法中,而不是在宏中,因为这是C++,我讨厌使用宏。我最初的尝试是编写一种方法,例如

代码语言:javascript
复制
void SafeRelease(IUnknown **ppInterface) {
    if(*ppInterface) {
        (*ppInterface)->Release();
        (*ppInterface) = nullptr;
    }
}

但是,将此方法应用于IDirect3DSurface9 *,例如,像SafeRelease(&mySurface)一样,错误IDirect3DSurface9 **IUnknown **是不兼容的。

  1. 我在这里做错什么了?
  2. 是否有更好的方法(希望不使用宏)来实现这样的函数?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-04 22:20:14

以下是我的方法:

代码语言:javascript
复制
template <typename T> void SafeRelease(T*& ptr)
{
    if(ptr)
    {
        ptr->Release();
        ptr = nullptr;
    }
}

示例用法:

代码语言:javascript
复制
IDirect3DDevice9 *pD3DDevice = NULL;
d3d->CreateDevice(..., &pD3DDevice);
SafeRelease(pD3DDevice);

如果需要,可以使用inline函数。

票数 1
EN

Stack Overflow用户

发布于 2013-02-04 21:53:27

您可以使用一个模板:

代码语言:javascript
复制
template<class DXInterface>
void SafeRelease(DXInterface **ppInterface) {
    if(*ppInterface) {
        (*ppInterface)->Release();
        (*ppInterface) = nullptr;
    }
}

您还可以使用std::unique_ptr或std::shared_ptr自动清除:

代码语言:javascript
复制
#include <memory>
#include <iostream>

struct Releaser {
   template<class DXInterface>
   void operator()(DXInterface *pInterface) const {
       if(pInterface) {
           pInterface->Release();
       }
   }
};

// For illustrative purposes only (supplied in DX9 headers)
struct IDirect3DSurface9 { void Release() { std::cout << "Released surface\n";} };
struct IDirect3DTexture9 { void Release() { std::cout << "Released texture\n";} };

void DX9CreateSurface( IDirect3DSurface9** surface ) 
{ 
    *surface = new IDirect3DSurface9();
}

void DX9CreateTexture( IDirect3DTexture9** texture ) 
{ 
    *texture = new IDirect3DTexture9();
}

// Your factory functions
IDirect3DSurface9* createSurface( /*init params go here*/ )
{
    IDirect3DSurface9* surface;
    DX9CreateSurface( &surface );
    return surface;
}

IDirect3DTexture9* createTexture( /*init params go here*/ )
{
    IDirect3DTexture9* texture;
    DX9CreateTexture( &texture );
    return texture;
}

int main()
{
  typedef std::unique_ptr<IDirect3DSurface9, Releaser> SurfacePtr;
  typedef std::unique_ptr<IDirect3DTexture9, Releaser> TexturePtr;

  SurfacePtr surface( createSurface() );
  TexturePtr texture( createTexture() );
  // ... use surface and texture here
  // Automatically released here when their lifetimes ends.
}

请注意,它们使用相同的Releaser,并注意,对surface.reset()的调用也会释放接口,并将unique_ptr内的指针设置为null以引导。这两个对象可能是类的成员,而不是main()中的对象。

票数 0
EN

Stack Overflow用户

发布于 2014-05-02 15:17:42

我在这里做错什么了?

我也有同样的问题,也是关于COM SafeRelease的。下面是这样的:

代码语言:javascript
复制
void SafeRelease(IUnknown **ppInterface) 
...
IDirect3DSurface9 * mySurface = new ...
...
SafeRelease(&mySurface);

IDirect3DSurface9 *,通过继承,可以转换为IUnknown *。但是,与直觉相反,不能将IDirect3DSurface9 **转换为IUnknown **。如果允许,那么在您的SafeRelease(IUnknown**)中您可以执行以下操作:

代码语言:javascript
复制
// obtain a pointer to an instance of some random subinterface of IUnknown
*ppInterface = pMyRamdomComInterfacePointer;

因此,我们会在指向IUnknown的指针中存储一个指向随机IDirect3DSurface9导数的指针。这将违反C++类型系统。这就是为什么不允许将T**转换为T**的任何其他类型。换句话说,T**类型的变量只能分配给ppT (T**类型的值),而不能指定ppSomeSubytpeOfT

比较一下这个:How come a pointer to a derived class cannot be passed to a function expecting a reference to a pointer to the base class?和这个:Casting double pointers of base classes

对于COM SafeRelease,可以使用模板(如这里所建议的)或宏。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14696202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档