WEB开发网
开发学院软件开发VC 用ATL建立轻量级的COM对象(6) 阅读

用ATL建立轻量级的COM对象(6)

 2006-07-21 11:44:26 来源:WEB开发网   
核心提示: 使用这种技术的类(包括大多数 ATL 基类)需要当心,不要调用构造器中的虚函数,用ATL建立轻量级的COM对象(6)(2),但是,为了在初始化时允许对虚函数的调用,使得基于 ATL 的工程不用C运行库就能进行链接,(在 DllMain / WinMain 以前,ATL 的 Creators

使用这种技术的类(包括大多数 ATL 基类)需要当心,不要调用构造器中的虚函数。但是,为了在初始化时允许对虚函数的调用,ATL 的 Creators 调用 FinalConstruct 方法,在这个方法中进行所有重要的初始化工作。在 FinalConstuct 中,从C++的角度看,你的类已经完全构造好了,也就是说你的所有对象的 vptr 完全被派生化。同时,基于 CComObject 的打包器也同时构造好了,允许你存取在 COM 聚合或 tear-off 情况下无法知道的控制。

如果在调试器中单步顺序执行 Creator 调用,你将注意到在缺省情况下对 InternalFinalConstructAddRef 和 InternalFinalConstructRelease 的调用什么也没做,但是,如果你打算在你的 FinalConstruct 实现中创建 COM 聚合,你可能会临时增加一次对象的引用计数,以防止它过早销毁(这发生在某个聚合对象调用 QueryInterface时)。你能通过添加下面的类定义行进行自我保护: DECLARE_PROTECT_FINAL_CONSTRUCT()
   
这一行代码重新定义了类的 InternalFinalConstructAddRef 和 InternalFinalConstructRelease 来增减引用计数,从而安全地传递可能调用 QueryInterface 的对象指针。

每一个基于ATL的工程都包含着一个 CComModule 派生类的实例。除了实现前面提到过的服务器生命期行为外,CComModule 还维持着一个 CLSID 到 ClassObject 的映射(叫做对象映射 Object Map)向量来提供所有外部可创建类。这个对象映射被用于实现进程内服务器的 DllGetClassObject,并且它为进程外服务器每次调用 CoRegisterClassObject 提供参数。虽然能直接显式地使用 CComClassFactory 和 Creator 类,但通常都是在 ATL 对象映射基础的上下文中使用。 ATL Object Map 是一个_ATL_OBJMAP_ ENTRY结构数组: struct _ATL_OBJMAP_ENTRY {
  const CLSID* pclsid;
  HRESULT (*pfnUpdateRegistry)(BOOL bRegister);
  HRESULT (*pfnGetClassObject)(void* pv,
            REFIID riid, LPVOID* ppv);
  HRESULT (*pfnCreateInstance)(void* pv,
            REFIID riid, LPVOID* ppv);
  IUnknown* pCF;
  DWORD dwRegister;
  LPCTSTR (* pfnGetObjectDescription)(void);
}; 
pfnGetClassObject成员的调用是在第一次需要创建新的类对象时。这个函数被作为 Creator 函数(pfnCreateInstance)的第一个参数传递,并且返回的结果接口指针被缓存在pCF成员中。通过按需要创建类对象,而不是静态地实例化变量,就不再需要使用带虚函数的全局对象,使得基于 ATL 的工程不用C运行库就能进行链接。(在 DllMain / WinMain 以前,C运行时必须用来构造全局和静态变量。)

Tags:ATL 建立 轻量级

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接