《深入解析ATL》笔记(二)

 

ATLCOM的基本支持可以分为:对象和服务器 

3.1 回顾COM套间 

COM支持两种对象:多线程对象和单线程对象。多线程对象是那些能够自己完成同步工作的对象,而单线程对象是COM来处理同步问题。 

COM判断一个对象是单线程还是多线程取决于其生存套间。COM套间是一个或多个线程的组合。这些线程或是单线程或是多线程。 

对于在单线程套间中创建的对象的调用必须完成之后,才能服务下一个请求。 

多线程套间中创建对象必须随时准备接收到自任意数目线程的调用。 

ATL把COM对象分成几个层次: 

1, CComXXXThreadModel被CComObjectRootEx使用,用来提供线程安全定理对象生命周期和对象锁定的功能。 

2, CComObjectRootBase 和CComObjectRootEx提供用于IUnknown实现辅助函数。 

3, 我们的类从CComObjectRootEx派生,同时也实现我们自己接口的方法。 

4, CComObject提供IUnknown方法的真正实现. 

class CComSingleThreadModel 

{ 

public: 

 static ULONG WINAPI Increment(LPLONG p) {return ++(*p);} 

 static ULONG WINAPI Decrement(LPLONG p) {return --(*p);}  

}; 

class CComMultiThreadModel 

{ 

public: 

 static ULONG WINAPI Increment(LPLONG p)  

{return InterlockedIncrement(p);} 

 static ULONG WINAPI Decrement(LPLONG p)  

{return InterlockedDecrement(p);}  

}; 

用于数据同步 

class CComCriticalSection 

{ 

public: 

 void Lock() {EnterCriticalSection(&m_sec);} 

 void Unlock() {LeaveCriticalSection(&m_sec);} 

 void Init() {InitializeCriticalSection(&m_sec);} 

 void Term() {DeleteCriticalSection(&m_sec);} 

 CRITICAL_SECTION m_sec; 

}; 

 

class CComAutoCriticalSection 

{ 

public: 

 void Lock() {EnterCriticalSection(&m_sec);} 

 void Unlock() {LeaveCriticalSection(&m_sec);} 

 CComAutoCriticalSection() {InitializeCriticalSection(&m_sec);} 

 ~CComAutoCriticalSection() {DeleteCriticalSection(&m_sec);} 

 CRITICAL_SECTION m_sec; 

}; 

 class CComFakeCriticalSection 

{ 

public: 

 void Lock() {} 

 void Unlock() {} 

 void Init() {} 

 void Term() {} 

}; 

IUnknown实现的核心 

template <class ThreadModel> 

class CComObjectLockT 

{ 

public: 

 CComObjectLockT(CComObjectRootEx<ThreadModel>* p) 

 { 

  if (p) 

   p->Lock(); 

  m_p = p; 

 } 

 

 ~CComObjectLockT() 

 { 

  if (m_p) 

   m_p->Unlock(); 

 } 

 CComObjectRootEx<ThreadModel>* m_p; 

}; 

template <class ThreadModel> 

class CComObjectRootEx : public CComObjectRootBase 

{ 

public: 

 typedef ThreadModel _ThreadModel; 

 typedef _ThreadModel::AutoCriticalSection _CritSec; 

 typedef CComObjectLockT<_ThreadModel> ObjectLock; 

 

 ULONG InternalAddRef() 

 { 

  ATLASSERT(m_dwRef != -1L); 

  return _ThreadModel::Increment(&m_dwRef); 

 } 

 ULONG InternalRelease() 

 { 

  ATLASSERT(m_dwRef > 0); 

  return _ThreadModel::Decrement(&m_dwRef); 

 } 

 

 void Lock() {m_critsec.Lock();} 

 void Unlock() {m_critsec.Unlock();} 

private: 

 _CritSec m_critsec; 

}; 

 

template <> 

class CComObjectRootEx<CComSingleThreadModel> : public CComObjectRootBase 

{ 

public: 

 typedef CComSingleThreadModel _ThreadModel; 

 typedef _ThreadModel::AutoCriticalSection _CritSec; 

 typedef CComObjectLockT<_ThreadModel> ObjectLock; 

 

 ULONG InternalAddRef() 

 { 

  ATLASSERT(m_dwRef != -1L); 

  return _ThreadModel::Increment(&m_dwRef); 

 } 

 ULONG InternalRelease() 

 { 

  return _ThreadModel::Decrement(&m_dwRef); 

 } 

 

 void Lock() {} 

 void Unlock() {} 

}; 

CComObjectRootEx除了提供了线程安全,还能过基类CComObjectRootBase的QueryInerface提供静态表驱动实现 

BEGIN_COM_MAP(CIXXX) 

 COM_INTERFACE_ENTRY(IIXXX) 

END_COM_MAP() 

展开为如下 

 IUnknown* _GetRawUnknown() 

{ ATLASSERT(_GetEntries()[0].pFunc == _ATL_SIMPLEMAPENTRY); 

return (IUnknown*)((int)this+_GetEntries()->dw); }  

HRESULT _InternalQueryInterface(REFIID iid, void** ppvObject) 

{ return InternalQueryInterface(this, _GetEntries(), iid, ppvObject); } 

 const static _ATL_INTMAP_ENTRY* WINAPI _GetEntries() 

{ 

 static const _ATL_INTMAP_ENTRY _entries[] = { {&IID_IXX, 0, _ATL_SIMPLEMAPENTRY}, {0,0,0}}; 

return _entries; 

} 

到这里,开始讨论一下创建一个类对象, 

CIXXX* pObj = new CIXXX; 显然不行,因为IUnknown的方法没有实现; 

可以这样做,CComOject<CIXXX>* pObj = new CComObject<CIXXX>; 

下面看看创建自己的一个静态函数 

template <class Base> 

HRESULT WINAPI CComObject<Base>::CreateInstance(CComObject<Base>** pp) 

{ 

 ATLASSERT(pp != NULL); 

 HRESULT hRes = E_OUTOFMEMORY; 

 CComObject<Base>* p = NULL; 

 ATLTRY(p = new CComObject<Base>()) 

 if (p != NULL) 

 { 

  p->SetVoid(NULL); 

  p->InternalFinalConstructAddRef(); 

  hRes = p->FinalConstruct(); 

  p->InternalFinalConstructRelease(); 

  if (hRes != S_OK) 

  { 

   delete p; 

   p = NULL; 

  } 

 } 

 *pp = p; 

 return hRes; 

} 

typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, DWORD dw); 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
文名: 深入解析ATL(第2版) 原名: ATL Internals, 2nd Edition Working with ATL 8 别名: ATL 作者: (美)塔瓦瑞斯译者: 赖仪灵 曹雨田 资源格式: PDF 版本: 扫描版 出版社: 电子工业出版社书号: 9787121049859发行时间: 2007年11月01日 地区: 大陆 语言: 简体文 简介: 编辑推荐 ATL的发明人Jim Springfield亲自作序推荐。   四位顶尖的Windows编程专家倾力合作,绝对经典再现。   COMATL开发人员的必备宝典。   深入分析ATL实现COM内幕细节,展示COM应用的各类漂亮技巧。   ATL的经典指南现已更新到ATL 8和VisuaI Studio 2005:   四位顶尖的Windows编程专家在本书系统地揭示了ATL的内部工作原理,他们解释了ATL是 如何工作的,以及为什么要以这样的方式工作。通过本书,客户端开发人员可以掌握ATL的窗口、COM控件、MFC集成、Web服务代理生成等资源。服务端编程人员可以应用ATL的全COM服务器和对象服务、高吞吐量、高并发Web应用程序和服务的广泛支持。每个Windows开发人员都将从本书学到强大的方法来增加应用程序的灵活性、减少负载、最大化程序的透明度和可控性。   ·通过图表、示例代码和ATL的内部实现代码来揭密ATL的内部原理。   ·遍历向导以简化在普通应用程序ATL开发。   ·掌握C++、COMATL的字符串使用技巧。   ·利用ATL的智能类型:CComPtr、CComQIPtr、CComBSTR和CComVariant。   ·理解并正确实现IUnknown。   ·创建能从COM服务器暴露COM对象的粘合代码。   ·使用Canned Interface实现来支持对象的永久性、COM集合、枚举器和连接点。   ·使用ATL窗口类和控件建立独立的应用程序和UI组件。   ·使用ATL Servet开发可以运行在微软IIS上的Web应用程序。 虽然.NET系统从1998年才开始其发展进程。但它已经使很多开发人员的编程发生了革命性的变化,并在未来几年将持续得到改进。但是,COM编程(和 ATL)也依然非常有活力,对Microsoft内外的很多开发人员都非常重要。本书的第2版,与第1版一样,提供了您所需要的信息,使我们在这些技术上的投资也将获得最大的回报。                        ——Jim Springfield,ATL发明人 虽然ATL比较精深,但是这本书的讲解非常通俗易懂,语言比较简练,条理非常清楚。即使在读完这本书之后,它仍然可以作为参考书指导我们的开发和学习工作。我想,这就是好书的价值所在吧。            ——潘爱民,经典畅销书《深入解析Windows操作系统,第4版》译者 内容简介 本书主要介绍了ATL技术的原理、内部实现和应用技巧,由当今4 位顶尖的 Windows技术专家联合撰写。全书内容丰富,深入浅出,主要涵盖了ATL内部架构和实现方法、运用向导简化ATL开发、C++/COM/ATL字符串的使用技巧、理解并正确实现IUnknown、充分利用ATL提供的Smart Types、撰写能够暴露COM服务器上COM对象的粘合代码、利用Canned Interface实现来支持对象持久化/COM群集/枚举、利用ATL Windows类建构独立的应用程序和UI组件等的技术内容。本书适合于广大Windows开发人员阅读参考,是ATL开发人员的必备权威参考书籍。 作者简介 Christopher Tavares,目前在微软工作,是模式与实践方面的专家。有着超过25年的编程经验,涉及的平台从Sinclair ZX-81到多CPU信号处理硬件。 目录: 第2版序 第1版序 前言 致谢 关于作者 联系博文视点 第1章 你好,ATL 1.1 什么是ATL 1.2 创建COM服务器 1.3 插入COM类 1.4 添加属性和方法 1.5 实现附加接口 1.6 脚本支持 1.7 添加永久性 1.8 添加和激发事件 1.9 使用窗口 1.10 COM控件 1.11 容纳控件 1.12 ATL Server Web项目 1.13 总结 第2章 字符串和文本 2.1 字符串数据类型、转换类和辅助函数 2.2 智能BSTR类CComBSTR 2.3 CComBSTR类 2.4 CString类 2.5 总结 第3章 ATL智能类型 3.1 智能VARIANT类CComVariant 3.2 智能SAFEARRAY类CComSafeArray 3.3 智能指针类CComPtr和CComQIPtr 3.4 智能指针类CAutoPtr和CAutoVectorPtr 3.5 ATL内存管理器 3.6 总结 第4章 ATL对象 4.1 实现IUnknown 4.2 ATL的层次 4.3 线程模型支持 4.4 IUnknow核心 4.5 我们的类 4.6 CComObject以及其他 4.7 ATL创建者 4.8 调试 4.9 总结 第5章 COM服务器 5.1 回顾COM服务器 5.2 对象映射表和CAtlModule类 5.3 对象映射表 5.4 对象映射类要求的方法 5.5 CAtlModule类 5.6 重游CComCoClass 5.7 ATL与C运行时库 5.8 总结 第6章 接口映射表 6.1 回顾:COM的实体身份 6.2 表驱动的QueryInterface 6.3 多重继承 6.4 Tear-off接口 6.5 聚合:外部控制对象 6.6 接口映射表链 6.7 尽管说“不” 6.8 调试 6.9 扩展性 6.10 总结 第7章 ATL的永久性 7.1 回顾COM的永久性 7.2 ATL的永久性实现类 7.3 属性映射表 7.4 永久性实现 7.5 其他永久性实现 7.6 使用永久性添加“按值列集”的语义 7.7 总结 第8章 集合和枚举器 8.1 COM集合和枚举接口 8.2 枚举数组 8.3 枚举标准的C++集合 8.4 集合 8.5 ATL数据类型的标准C++集合 8.6 ATL集合 8.7 对象模型 8.8 总结 第9章 连接点 9.1 回顾连接点 9.2 创建基于ATL的可连接对象 9.3 创建一个接收事件的对象 9.4 它是怎么工作的:杂乱的实现细节 9.5 总结 第10章 窗口 10.1 Windows应用程序的结构 10.2 CWindow 10.3 CWindowImpl 10.4 CDialogImpl 10.5 Windows控件包装类 10.6 CContainedWindow 10.7 总结 第11章 ActiveX控件 11.1 回顾ActiveX控件 11.2 BullsEye控件需求 11.3 使用ATL向导创建初始的控件 11.4 初始的BullsEye源文件 11.5 逐步开发BullsEye控件 11.6 总结 第12章 控件包容 12.1 控件是如何被包容的 12.2 基本的控件包容 12.3 在对话框容纳控件 12.4 复合控件 12.5 HTML控件 12.6 ATL控件包容的限制 12.7 总结 第13章 你好,ATL Server:一个新型的C++ Web平台 13.1 微软Web平台(因特网信息服务) 13.2 可能是可以运行的最简单ISAPI扩展 13.3 封装ISAPI 13.4 ATL Server 13.5 ATL Server的Web服务 13.6 总结 第14章 ATL Server内幕 14.1 ATL Server的ISAPI实现 14.2 服务器响应文件 14.3 请求处理程序示例 14.4 输入处理 14.5 会话管理 14.6 数据缓存 14.7 总结 附录A 实例展示C++模板 A.1 模板的必要性 A.2 模板基础 A.3 不同类型的多态 A.4 函数模板 A.5 成员函数模板 A.6 总结 附录B ATL头文件 附录C 移植到ATL 8 C.1 字符串、字符集和转换 C.2 与MFC共享的类 C.3 实现COM服务器 C.4 ActiveX控件和控件容纳 C.5 ATL_MIN_CRT变化 C.6 总结 附录D 属性化ATL D.1 ATL Attributes的基础 D.2 属性化ATL的未来 D.3 总结 索引

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值