インターフェイスが IDL で適切に定義され、タイプ ライブラリにコンパイルされている場合、タイプ ライブラリIDispatch
を介した実装は、ITypeInfo
ほとんどが委譲であるため、非常に実行可能です。興味深いのITypeInfo::Invoke
は、正しい C++ v-table レイアウトに依存する部分です。
public class CComClass: public IDualInterface
{
// ...
// implementing IDualInterface
ITypeInfo* m_pTypeInfo // can be obtained via ITypeLib::GetTypeInfoOfGuid for the GUID of IDualInterface
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
if (0 != itinfo)
return E_INVALIDARG;
(*pptinfo = m_pTypeInfo)->AddRef();
return S_OK;
}
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
{
return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
}
STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
return m_pTypeInfo->Invoke(static_cast<IDualInterface*>(this), dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}
}
同様のアプローチを使用して、MSHTML DOM オブジェクトのスクリプト呼び出し可能なラッパーを作成し、スクリプトのセキュリティ制限を回避しました。
では、ITypeInfo はどこから取得するのでしょうか。基本的に、次の方法で取得します。
- インターフェイスをデュアルインターフェイスとして宣言する IDL ファイルを記述します。C++ にはリフレクション
ITypeInfo
がなく、言語に中立であるため、クラスで C++ 関数を直接呼び出すことはできません。したがってInvoke
、タイプ ライブラリで宣言されている別のメソッドへの呼び出しのみを委任できます。
- ビルド プロセスの一部として、IDL をヘッダー ファイルとタイプ ライブラリにコンパイルします。
- IDL から生成されたヘッダー ファイルは、実装クラスが継承する必要があるインターフェイスを定義します。すべてのメソッドを実装したら、準備完了です。(開発の場合は、それらをすべて返すことから始めて、
E_NOTIMPL
それらを 1 つずつ実装します)
- タイプ ライブラリをインストール先ディレクトリにインストールするか、EXE/DLL のリソースとしてインストールします。を呼び出して登録する必要があります
RegisterTypeLib
。リソースとして埋め込まれている場合は、DllRegisterServer
実装からこれを呼び出す必要があります。
- を使用して、オブジェクトの最初のインスタンスが作成されたときにタイプ ライブラリを読み込みます
LoadTypeLib
。これにより、ITypeLib
- を使用して必要な ITypeInfo を取得します
GetTypeInfoOfGuid
。