将 DirectX 接口强制转换为 IUnknown 指针
Cast DirectX interfaces to IUnknown pointers
我的代码中有相当多的接口,我想将重复Release
代码封装在另一个方法中而不是宏中,因为这很C++,而且我讨厌使用宏。我最初的尝试是编写一个方法,
void SafeRelease(IUnknown **ppInterface) {
if(*ppInterface) {
(*ppInterface)->Release();
(*ppInterface) = nullptr;
}
}
但是,将此方法应用于IDirect3DSurface9 *
例如SafeRelease(&mySurface)
会产生错误IDirect3DSurface9 **
与IUnknown **
不兼容。
- 我在这里做错了什么?
- 有没有更好的方法(希望不使用宏(来实现这样的功能?
的方法:
template <typename T> void SafeRelease(T*& ptr)
{
if(ptr)
{
ptr->Release();
ptr = nullptr;
}
}
用法示例:
IDirect3DDevice9 *pD3DDevice = NULL;
d3d->CreateDevice(..., &pD3DDevice);
SafeRelease(pD3DDevice);
如果需要,您可以inline
此功能。
您可以使用模板:
template<class DXInterface>
void SafeRelease(DXInterface **ppInterface) {
if(*ppInterface) {
(*ppInterface)->Release();
(*ppInterface) = nullptr;
}
}
您还可以使用 std::unique_ptr 或 std::shared_ptr 来自动清理:
#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 surfacen";} };
struct IDirect3DTexture9 { void Release() { std::cout << "Released texturen";} };
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(( 中的对象。
我在这里做错了什么?
我刚刚有同样的问题,也适用于 COM SafeRelease
.所以这里是:
void SafeRelease(IUnknown **ppInterface)
...
IDirect3DSurface9 * mySurface = new ...
...
SafeRelease(&mySurface);
IDirect3DSurface9 *
,凭借继承,可以铸造到IUnknown *
。但是,与直觉相反,IDirect3DSurface9 **
不能投射到IUnknown **
.如果允许,那么在您的SafeRelease(IUnknown**)
内,您可以执行以下操作:
// obtain a pointer to an instance of some random subinterface of IUnknown
*ppInterface = pMyRamdomComInterfacePointer;
因此,我们将在指向IDirect3DSurface9
的指针中存储指向某些随机IUnknown
导数的指针。这将违反C++类型系统。这就是为什么不允许将除T**
转换为T**
以外的任何其他类型的转换。换句话说,T**
类型的变量只能分配一个ppT
(类型 T**
的值(,而不能分配一个ppSomeSubytpeOfT
。
比较一下:为什么指向派生类的指针不能传递给期望引用指向基类的指针的函数?这个:强制转换基类的双指针。
对于 COM SafeRelease
,模板(如此处建议(或宏都可以。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 将 DirectX 接口强制转换为 IUnknown 指针
- 为什么通过同一COM对象的不同接口检索到的IUnknown*指针具有相同的值?