2011-11-10 20 views
1

私はIDispatch/IUnknownポインタを介して見る__vfptrと混乱しました。 私はin-procフリースレッドCOMオブジェクト(IMyContainer)を作成しています。このオブジェクトの中で、同じIMyInterfaceを実装するcomオブジェクトの2つの異なるインスタンスへのポインタを保持する必要があります。私はCreateAndSaveDispToMap()を2回呼び出します。2つの異なるインスタンスで同じ__vfptrが表示されるのはなぜですか?

私の考えは、いくつかのstd :: mapにIDispatchポインタを保持することです。現時点では、各インスタンスのrefCountが1になると思われます。そうです。しかし驚いたことに、私は2つの異なるディスパッチポインタのためにpUnkを使って同じ__vftblを取得していることがわかります。

なぜですか? AddRef()とRelease()がうまく動作するのはどうでしょうか?

HRESULT CMyContainer::CreateAndSaveDispToMap(...) 
{ 
... 
IMyInterface* pMyInterface = NULL; 
hr = ::CoCreateInstance(CLSID_MyInterface, NULL, CLSCTX_INPROC_SERVER, IID_IMyInterface, (void**)&pMyInterface); 
pMyInterface->QueryInterface(IID_IDispatch, (void**)&pDisp); 
pMyInterface->Release(); // Call Release since QI already called AddRef() 
... 

IUnknown* pUnk = NULL; 
pDisp->QueryInterface(IID_IUnknown, (void**)&pUnk); 
int refCount = pUnk->Release(); 
... 
AddToMap(pDisp); 
} 
+0

vテーブルは単なるアドレステーブルです。すべてのオブジェクトインスタンスに対して* 1つの* vテーブルがあり、オブジェクト状態を格納しません。 –

答えて

0

各多型オブジェクトは、オブジェクトの実際のクラスの仮想テーブルへのポインタである__vfptrを有することになります。各クラスごとに1つのvtableが生成されます。だからこそ、同じクラスのどんな2つのオブジェクトでも、同じ値を持つのは__vfptrです。

異なるCOMオブジェクトを区別するために、IUnknownインターフェイスポインタを取得して比較します。それはobject identityと呼ばれています。

0

ありがとうございました。私は、IUnknownの関数のアドレスは同じであり、そうでなければならないことを理解しました。

しかし、まだAddRef/Releaseの動作を見落とさないでください。 ExposePointer()でデバッグモードに入ると、2回目の呼び出しでrefCountが3にならないことがわかります。

しかし、私がForgetExposePointer()を2回呼び出すと、 3.

Variant *を使用してディスパッチポインタを返す理由結果またはそのような値を返すことを忘れると、私は異なる結果になりますか?私は、コール1とコール2の間で、Release()へのいくつかの隠されたコールが発生することを理解しています...

STDMETHODIMP CMyContainer::ExposePointer([in]int index, [out, retval] VARIANT* Result) 
{ 
VariantInit(Result); 
IDispatch* pDisp = m_map[index].second; 
V_VT(Result) = VT_DISPATCH; 
V_DISPATCH(Result) = pDisp; 
refCount_x = pDisp->AddRef(); // Increment, because we expose 
} 

STDMETHODIMP CMyContainer::ForgetExposePointer([in]int index, [out, retval] VARIANT* Result) 
{ 
VariantInit(Result); 
IDispatch* pDisp = m_map[index].second; 
refCount_y = pDisp->AddRef(); 
} 


MyApp::Function1(...) 
{ 
CreateAndSaveDispToMap(...); // refCount is 1 now 
VARIANT var1; 
VARIANT var2; 
pMyContainer->ExposePointer(index, &var1); // Call 1 
pMyContainer->ExposePointer(index, &var2); // Call 2 
} 
MyApp::Function2(...) 
{ 
CreateAndSaveDispToMap(...); // refCount is 1 now 
VARIANT var1; 
VARIANT var2; 
pMyContainer->ForgetExposePointer(index, &var1); 
pMyContainer->ForgetExposePointer(index, &var2); 
} 
関連する問題