<com原理>与<com内幕>的聚合实现部分

转载 2013年02月16日 12:36:46

原文出自:http://www.cnblogs.com/sosopop/archive/2010/07/25/1784613.html

觉得写得很不错,转载下

 

可以聚合的com需要在内部实现一个代理INondelegatingUnknown接口,并在类厂创建第一个接口的时候,检查

      //  iid must be IID_IUnknown for aggregating
      if ( ( pUnknownOuter != NULL ) && ( iid != IID_IUnknown ) )
      {          

     return CLASS_E_NOAGGREGATION; 

    }

如果是被聚合的,则查询的第一个接口必须是IUnknown,然后不管是否是被聚合状态还是非被聚合状态(判断pUnknownOuter是否为空)工厂都会返回代理INondelegatingUnknown的接口指针,而不是平常的IUnknown,可以聚合的组件内部接口的查询和实现都是通过INondelegatingUnknown来进行的。

 

      CA *pObj=new CA (pUnknownOuter);
      if (NULL==pObj)          return hr; 
      //Obtain the first interface pointer (which does an AddRef)
      hr = pObj->NondelegationQueryInterface(iid, ppv);

 

类厂创建完毕后通过方法NondelegationQueryInterface来查询所需要的接口对象指针。没有被聚合时都是通过INondelegatingUnknown来进行查询的接口对象指针的,这一点和普通com组件几乎是一样的,但也有一部分不同。如果查询的接口是IUnknown接口指针则返回INondelegatingUnknown的指针,因为IUnknown与INondelegatingUnknown的虚表接口是一样的,因此强转后通过IUnknown的查询都会转到INondelegatingUnknown上,但通过INondelegatingUnknown查询到的其他接口指针再进行查询的时候,(比如IX->QueryInterface())他们会调用虚表中真正的IUnknown的方法,而不是代理的,这时候就需要通过判断自己当前是否是被聚合的(判断pUnknownOuter)如果是被聚合的,则调用pUnknownOuter->QueryInteface发送给上层进行查询,如果没有聚合,则继续跳转到INondelegatingUnknown的接口上进行查询。


这里COM原理与COM技术内幕的聚合com的QueryInteface是有点区别的


com原理是这样实现的

HRESULT CA::QueryInterface(const IID& iid, void **ppv)
{
      if  ( m_pUnknownOuter != NULL )
              return m_pUnknownOuter->QueryInterface(iid, ppv);
      else
              return NondelegationQueryInterface(iid, ppv);
}

 

通过m_pUnknownOuter来判断似乎否是被聚合状态 。

 

而com技术内幕实现是:

 

HRESULT CA::QueryInterface(const IID& iid, void **ppv)
{
       return m_pUnknownOuter->QueryInterface(iid, ppv);
}

这里我们就奇怪了,他为什么没有判断呢

 

原因就在构造函数给 m_pUnknownOuter进行复制的时候,采用的一点小技巧。在构造函数中会判断传入的pUnknownOuter是否为空,如果pUnknownOuter是空的话,则
m_pUnknownOuter = reinterpret_cast<IUnknown*>(static_cast<INondelegationUnknown*>(this));
由于IUnKnown与INondelegationUnknown虚表是一样的,因此通过reinterpret_cast直接强转使m_pUnknownOuter直接指向INondelegationUnknown的虚表。这样之后所有调用m_pUnknownOuter就不用进行判断是否是被聚合的了。

 

 为什么要使用这层代理呢?

当我们通过外部的com组件聚合一个内部的com组件的时候,会把外部的IUnknown指针传递给内部保存,外部查询一个内部的接口插叙不到的时候,就会调用内部的组件进行查询,内部组件查询到接口会,会返回接口的指针。根据com规范,如果IA可以查到IB,则IB也可以查询到IA,而被聚合的IB不知道IA的存在这时候就需要调用之前外部传入的m_pUnknownOuter进行查询这里就用到了我们上面所说的判断是否被聚合,如果被聚合的话则调用m_pUnknownOuter进行查询。

问题也就在这里

情况一,如果外部组件通过接口IA查询IB查询不到,则-》》》调用就会调用内部聚合的组件进行查询-》》》聚合组件接口的QueryInterface-》》》实际调用到聚合组件接口的NondelegationQueryInterface-》》》查询到IB直接返回接口指针,查询不到返回没有接口。

情况二,如果通过IB来查找IXXX通过真正的IUnknown的QueryInterface-》》》,发现是被聚合的则调用m_pUnknownOuter进行查询,这时候就按情况一继续进行了。

也就是说,搜有查询最后都会汇集到NondelegationQueryInterface

IA->QueryInterface() --------> INondelegationUnknown->NondelegationQueryInterface

IB->QueryInterface() --------> IA->QueryInterface() --------> INondelegationUnknown->NondelegationQueryInterface

如果不存在INondelegationUnknown接口的话,查询一个不存在的接口,机会陷入接口查询的死循环了,外部查不到,调用内部,内部又调用外部。

对于使用代理来进行接口查询主要还是为了统一聚合和非聚合接口的查询,全部采用自外而内的查询方式。

<com原理>与<com内幕>的聚合实现部分。

原文出自:http://www.cnblogs.com/sosopop/archive/2010/07/25/1784613.html 觉得写得很不错,转载下   可以聚合的com需要在内部实现一个...
  • bestwolf1983
  • bestwolf1983
  • 2011年08月08日 09:51
  • 489

COM原理之包容与聚合

1.包容和聚合的概念包容和聚合实际上是使一个组件使用另外一个组件的一种技术。包容的情况下,客户只能看到外部组件的接口,而外部组件接口的实现是通过转发给内部组件实现的。聚合的情况下,直接将内部组件的借口...
  • xsh_123321
  • xsh_123321
  • 2010年09月08日 11:36
  • 2158

COM原理与实现之二: 聚合

COM原理与实现之二: 聚合C++没有同聚合等价的特性。聚合实际上是继承性的一种动态形式。而C++的继承总是静态的,是实现继承。COM是接口继承,通过聚合接口,可以做成动态配置。研究COM,主要是利用...
  • cheungmine
  • cheungmine
  • 2016年06月14日 00:05
  • 5940

《COM原理与应用》学习笔记

 为了学习ActiveX插件的编写,从这几天开始学习COM原理。ActiveX是以COM为基础的,所以要想要比较深入的学习ActiveX技术需要先学习COM原理。   COM是微软提出的组件标...
  • dennisxie1992
  • dennisxie1992
  • 2014年09月08日 17:14
  • 586

COM技术内幕学习笔记---第八章---组件复用:包容和聚合

COM 不支持实现继承的原因在于这种继承方式将 使得一个对象的实现同另外一个对象的实现紧紧地关联起来。 在这种情况下,当基类的实现被修改之后,派生类将无法正常运行而必须被修改。对于一个中等规模的C+...
  • shb8845369
  • shb8845369
  • 2014年04月08日 15:06
  • 1329

【COM原理和应用】1、COM原理和概述

【我们知道,Directshow整体上是构建在COM之上的,也可以认为是COM在视频、流媒体领域的一种特定的应用和封装。如果只是为了开发High level的directshow应用,COM方面的只是...
  • shaqoneal
  • shaqoneal
  • 2015年01月31日 18:36
  • 748

COM---组件复用:包容与聚合

包容和 聚合为实现组件复用和定制提供了一种极鲁棒性的机制。使得COM框架下不需要实现继承,客户通组件的实现完全隔离开。 如果希望给组件增加新的接口,可以使用聚合。聚合是包容的一个特例。以下代码只列出...
  • u012319493
  • u012319493
  • 2017年02月16日 19:05
  • 451

COM 对象聚合

无论是对象聚合或是对象包容,其作用都是组件的复用,使用环境是这样的,有组件some对象和other对象,我们暴露出来的是some对象,现在需求改变了,some要加入新 的功能,而该功能已经被othe...
  • dasgk
  • dasgk
  • 2013年05月28日 17:00
  • 898

COM聚合的实现

聚合指的是COM对象转接客户端对某个接口的请求。某COM对象B并不实现ISomeInterface接口,但是可以通过调用某个内部COM对象A来支持该接口。意思是指,当客户端调用B所支持的接口IOthe...
  • pc_fly
  • pc_fly
  • 2008年01月11日 00:03
  • 295

COM原理与实现之一

COM原理与实现之一COM组件其实是一种特殊的对象体系,遵循一个统一的标准,使到各个软件都可以通过某种方法访问这个对象的方法,也就可以做到组件调用。COM就是统一的标准——通过接口来调用COM组件。接...
  • cheungmine
  • cheungmine
  • 2016年06月12日 10:25
  • 5811
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:<com原理>与<com内幕>的聚合实现部分
举报原因:
原因补充:

(最多只允许输入30个字)