天天看點

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      如需轉載請自行聯系原作者

繼續閱讀