天天看点

DCOM(分布式组件对象模型)原理浅析(二)

今天我们来分析QueryInterface函数。

<a href="https://s5.51cto.com/oss/201711/22/38d0cab7fa23ec2768adbcc1cfed8117.png-wh_500x0-wm_3-wmp_4-s_3770056964.png" target="_blank"></a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

<code>HRESULT</code> <code>CDictionary::QueryInterface(</code><code>const</code> <code>IID&amp; iid, </code><code>void</code> <code>**ppv)</code>

<code>{</code>

<code>    </code><code>if</code><code>(iid == IID_IUnknown)</code>

<code>    </code><code>{</code>

<code>        </code><code>*ppv = (IDictionary*)</code><code>this</code><code>;</code>

<code>        </code><code>((IDictionary*)(*ppv))-&gt;AddRef();       </code>

<code>    </code><code>}elseif(iid == IID_Dictionary)</code>

<code>        </code><code>((IDictionary*)(*ppv))-&gt;AddRef();</code>

<code>    </code><code>}elseif(iid == IID_SpellCheck)</code>

<code>        </code><code>*ppv = (ISpellCheck*)</code><code>this</code><code>;</code>

<code>        </code><code>((ISpellCheck*)(*ppv))-&gt;AddRef();</code>

<code>    </code><code>}</code>

<code>    </code><code>else</code>

<code>        </code><code>*ppv = NULL;</code>

<code>        </code><code>return</code> <code>E_NOINTERFACE;</code>

<code>    </code> 

<code>    </code><code>return</code> <code>S_OK;  </code>

<code>}</code>

根据COM接口的内存接口以及C++语言中类多重继承的内存结构,我们实现QueryInterface函数。

QueryInterface函数对于iid的三种可能值分别进行了处理,不管客户要想查询字典对象所支持的哪个接口,QueryInterface都会返回相应的接口指针,如图,当我们将this指针转换为基类指针时,所得到的指针正好指向接口的vtable,所以我们用类型转换函数就可以得到每个接口的vtable,也就是接口指针。

在第一个if语句块中,我们并没有把this指针直接转换为IUnknown指针,根据C++语法,由于在CDictionary的基类树中,有两个IUnknown节点,因此直接把this指针转换成IUnknown指针存在二义性。

先把this指针转换成IDictionary或者ISpellCheck,再转换成IUnknown,但必须保证每次查到的IUnknown接口完全一致。

这个程序直接把IDictionary接口指针当做IUnknown接口指针,这样的转换是符合COM规范的。

根据CDictionary的基类树,这里的继承关系不能用虚拟继承,否则就不能保证IDictionary和ISpellCheck的vtable与COM接口的vtable的一致性。

本文转自 liam2199 博客,原文链接:     http://blog.51cto.com/liam2199      如需转载请自行联系原作者

继续阅读