CComPtr

公開:2009-10-11 18:21
更新:2020-02-15 04:36
カテゴリ:c++

VC Express EditionにはATLがついてないので、CComPtr(COMスマートポインタ)がない。
boost::intrusive_ptrで代用していた(ちなみに代用方法はこちら参照)のだが、どうにも面倒臭いのでググってみたらやはりCComPtrクローンを作っている人がいた。
http://www.codeproject.com/KB/COM/ccomptr.aspx
http://www.firefly-vj.net/imagery/?itemid=354
上記2つを適当にマージして作ったのが下記コード。


#ifndef _COMPTR_H_
#define _COMPTR_H_
template<class INTERFACE, const IID* piid = NULL>
class CComPtr
{
public:
CComPtr()
{
interface_ = NULL;
}
CComPtr(INTERFACE* lPtr)
{
interface_ = NULL;
if (lPtr != NULL)
{
interface_ = lPtr;
interface_->AddRef();
}
}
CComPtr(const CComPtr<INTERFACE, piid>& RefComPtr)
{
interface_ = NULL;
interface_ = (INTERFACE*)RefComPtr;
if (interface_)
{
interface_->AddRef();
}
}
CComPtr(IUnknown* pIUnknown, IID iid)
{
interface_ = NULL;
if (pIUnknown != NULL)
{
pIUnknown->QueryInterface(iid, (void**)&interface_);
}
}
~CComPtr()
{
if (interface_)
{
interface_->Release();
interface_ = NULL;
}
}
public:
operator INTERFACE*() const
{
return interface_;
}
INTERFACE& operator*() const
{
return *interface_;
}
INTERFACE** operator&()
{
return &interface_;
}
INTERFACE* operator->() const
{
return interface_;
}
INTERFACE* operator=(INTERFACE* lPtr)
{
if (IsEqualObject(lPtr))
{
return interface_;
}
interface_->Release();
lPtr->AddRef();
interface_ = lPtr;
return interface_;
}
INTERFACE* operator=(IUnknown* pIUnknown)
{
assert(pIUnknown != NULL);
assert(piid != NULL);
pIUnknown->QueryInterface(*piid, (void**)&interface_);
assert(interface_ != NULL);
return interface_;
}
INTERFACE* operator=(const CComPtr<INTERFACE, piid>& RefComPtr)
{
assert(&RefComPtr != NULL);
interface_ = (INTERFACE*)RefComPtr;
if (interface_)
{
interface_->AddRef();
}
return interface_;
}
void Attach(INTERFACE* lPtr)
{
if (interface_)
{
interface_->Release();
}
interface_ = lPtr;
}
INTERFACE* Detach()
{
INTERFACE* lPtr = interface_;
interface_ = NULL;
return lPtr;
}
void Release()
{
if (interface_)
{
interface_->Release();
interface_ = NULL;
}
}
bool IsEqualObject(IUnknown* pOther)
{
assert(pOther != NULL);
IUnknown* pUnknown = NULL;
interface_->QueryInterface(IID_IUnknown, (void**)&pUnknown);
bool Result = (pOther == pUnknown) ? true : false;
pUnknown->Release();
return Result;
}
HRESULT CreateInstance(const GUID &clsid, IID iid=GUID_NULL)
{
if(IsEqualObject(iid, GUID_NULL)) iid=__uuidof(T);
HRESULT hr = ::CoCreateInstance(clsid, NULL
,CLSCTX_INPROC_SERVER
,iid
,(void**)(&interface_));
return hr;
}
private:
INTERFACE* interface_;
};
#endif // _COMPTR_H_

しかし、今頃になってCOM Interfaceラッパを作る羽目になるとは。。。