用ATL建立轻量级的COM对象(4)
2006-07-21 11:44:34 来源:WEB开发网第一部分:为什么要使用ATL。
第二部分:起步篇。
第三部分:实现IUnknown。
实现接口
现在你已经积累了一些关于ATL线程模型方面的知识,下面我们来讨论ATL如何实现IUnknown。ATL最不直观的(同时也是最强大的)一个方面就是你要实现的类事实上都是不能被直接实例化的抽象类。实现一个从通用的IUnknown派生的C++类。但是在确定对象的运行环境之前,QueryInterface,AddRef 和 Release是不会有实质性代码的。这种灵活性使开发人员能实现对象的关键功能,如COM的聚合支持,tear-offs,堆和栈分配,服务器锁定等等。下图展示了一个典型的基于ATL的类层次。
图四 典型的基于ATL的类层次
从下面的代码可以看出,ATL中实现IUnknown的关键在于CComObjectRootBase 和 CComObjectRootEx。
CComObjectRoot
class CComObjectRootBase {
public:
// C++ 构造函数
CComObjectRootBase() { m_dwRef = 0L; }
// ATL 伪构造函数和伪析构函数
HRESULT FinalConstruct() { return S_OK; }
void FinalRelease() {}
// 内部Unknown函数(由派生类提供的InternalAddRef/Release)
static HRESULT WINAPI InternalQueryInterface(void* pThis,
const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) {
HRESULT hRes = AtlInternalQueryInterface(pThis,pEntries,iid,ppvObject);
return _ATLDUMPIID(iid, pszClassName, hRes);
}
// 外部Unknown函数
ULONG OuterAddRef() { return m_pOuterUnknown->AddRef(); }
ULONG OuterRelease() { return m_pOuterUnknown->Release(); }
HRESULT OuterQueryInterface(REFIID iid, void ** ppvObject)
{ return m_pOuterUnknown->QueryInterface(iid, ppvObject); }
// ATL 创建者的钩子例程
void SetVoid(void*) {}
void InternalFinalConstructAddRef() {}
void InternalFinalConstructRelease() {}
// ATL 接口映射辅助函数
static HRESULT WINAPI _Break( void*, REFIID, void**, DWORD);
static HRESULT WINAPI _NoInterface( void*, REFIID, void**, DWORD);
static HRESULT WINAPI _Creator( void*, REFIID, void**, DWORD);
static HRESULT WINAPI _Delegate( void*, REFIID, void**, DWORD);
static HRESULT WINAPI _Chain( void*, REFIID, void**, DWORD);
static HRESULT WINAPI _Cache( void*, REFIID, void**, DWORD);
// 实际的引用计数或者指针返回到真实的Unknown
union {
long m_dwRef;
IUnknown* m_pOuterUnknown;
};
};
template <class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase {
public:
typedef ThreadModel _ThreadModel;
typedef _ThreadModel::AutoCriticalSection _CritSec;
// 内部 Unknown 函数(InternalQueryInterface 由 CComObjectRootBase提供)
ULONG InternalAddRef() { return _ThreadModel::Increment(&m_dwRef); }
ULONG InternalRelease() { return _ThreadModel::Decrement(&m_dwRef); }
// 对象级的锁定操作
void Lock() {m_critsec.Lock();}
void Unlock() {m_critsec.Unlock();}
private:
_CritSec m_critsec;
};
- ››建立唯美图片特效,十个jQuery插件分享
- ››建立自己的TextView和ImageView的组合View类
- ››轻量级数据交换格式 JSON轻松入门
- ››建立虚拟专用网 使用SSH保护网络通信
- ››轻量级系统 Lubuntu 10.04 发布
- ››建立一个 Derby 日历,第 3 部分: 使用事务和锁定...
- ››建立一个 Derby 日历,第 3 部分: 使用事务和锁定...
- ››建立一个 Derby 日历,第 1 部分: 理解 JDBC
- ››建立一个 Derby 日历,第 2 部分: 嵌入选项(上)...
- ››建立一个 Derby 日历,第 2 部分: 嵌入选项(下)...
- ››建立 qt for symbian 的开发环境
- ››建立一个 Android 项目的实例
更多精彩
赞助商链接