{C++} COM 组件多层聚合嵌套原理


    大四的课还是蛮有意思的,其中有一个COM组件的课,感觉挺有收获,做了一个小Demo,是关于COM聚合的, 

 聚合和包容是COM的基本特征,老师上课没把这俩的关系讲清楚,也不大知道为啥放着简单的包容不用,用聚合写模块。

通过做这个Demo,俺算是理解了。因为包容只是单向调用接口,也就是从外到内,不能从内到外。而聚合则是双向调用的,

非常的灵活。下面通过具体的例子说说。

 

    这个小Demo是控制台调用三个动态链接库的,每个链接库中都有一个方法,最外面的库CompB.dll里面是减法运算, 

 聚合CompC.dll里面的乘法,CompC.dll聚合CompA.dll里面的加法。CompB.dll调用接口是OtherInterface,CompC.dll

调用接口是AnyInterface,CompA.dll调用接口是SomeInterface。 CompB内部指针Inner指向CompC,CompC内部指针 

Inner指向CompA,Outer指针指向CompB,CompA内部指针Outer指针指向CompC,通过这四个指针,可以使接口查询

双向传递。也就是说我可以通过OtherInterface拿到CompA的Add方法,也可以通过SomeInterface拿到CompB的Minus

方法,调用方式非常灵活。三个接口无论调用哪一个都可以访问到三个动态链接库中的所有方法。每一个方法都可以通过不同

接口调用,原理也很清晰和简单。多层聚合调用的中间层dll就需要一对指针指向上层dll和下层dll,就像CompC一样。实现也不

复杂,每个动态链接库都有一个查询接口方法,CompC和CompA通过非委托查询接口,进行调用传递。初始化过程是这样的,

CompB初始化CompC实例,CompC初始化CompA实例。CompB如果希望调用CompA就必须先初始化CompC,初始化过

程也很清晰。为了模块的灵活性,多写些代码还是值得滴。


基本原理如图:


 

我本地的执行输出: 

 

 

 

多层聚合嵌套核心方法是CompC的两个查询方法:

QueryInterface: 

 1  HRESULT CC::QueryInterface( const  IID &  iid,  void   ** ppv)
 2  {
 3      printf( " ---------------------excute CompC QueryInterface!!!\n " );
 4       if  ( iid  ==  IID_OtherInterface ) 
 5      {
 6           if (m_pUnknownOuter  !=  NULL){
 7              printf( " CompC m_pUnknownOuter is not null!\n " );
 8               return  m_pUnknownOuter -> QueryInterface(iid, ppv);
 9          } else {
10               return  NondelegationQueryInterface(iid, ppv);
11          }
12      }
13       if  ( iid  ==  IID_SomeInterface ) {
14           if   ( m_pUnknownInner  !=  NULL ){
15              printf( " CompC m_pUnknownInner is not null!\n " );
16               return  m_pUnknownInner -> QueryInterface(iid, ppv);
17          }  else {
18               return  NondelegationQueryInterface(iid, ppv);
19          }
20      }  else  {
21           return  NondelegationQueryInterface(iid, ppv);
22      }
23  }

 

 NondelegationQueryInterface:

 

 1  HRESULT CC::NondelegationQueryInterface( const  IID &  iid,  void   ** ppv)
 2  {
 3      printf( " ---------------------excute CompC NondelegationQueryInterface!!!\n " );
 4       if  ( iid  ==  IID_IUnknown )
 5      {
 6           * ppv  =  (INondelegatingUnknown  * this  ;
 7          ((IUnknown  * )( * ppv)) -> AddRef() ;
 8      }  else   if  ( iid  ==  IID_AnyInterface ) 
 9      {
10           * ppv  =  (IAnyInterface  * this  ;
11          ((IAnyInterface  * )( * ppv)) -> AddRef() ;
12      }  else   if  ( iid  ==  IID_SomeInterface ) 
13      {
14           return  m_pUnknownInner -> QueryInterface(iid, ppv) ;
15      }  else   if  ( iid  ==  IID_OtherInterface ) 
16      {
17           return  m_pUnknownOuter -> QueryInterface(iid, ppv) ;
18      }  else
19      {
20           * ppv  =  NULL;
21           return  E_NOINTERFACE ;
22      }
23       return  S_OK;
24  }

 

网上这方面东西不多,发篇帖子填补一下。 为这方面不太清楚的同学提供下帮助。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值