Win32 API 日本語リファレンス
ホームSystem.Com.Marshal › IMarshal

IMarshal

COM
IID00000003-0000-0000-c000-000000000046継承元IUnknown自前メソッド開始 vtbl3

公式ドキュメント

IMarshal (objidlbase.h) インターフェイスは、COM オブジェクトが自身のインターフェイス ポインターのマーシャリングを定義および管理できるようにします。

解説(Remarks)

マーシャリングとは、別のプロセスやコンピューターへ送信するために、データをパケットへパッケージ化する処理です。アンマーシャリングは、受信側でそのデータを復元する処理です。任意の呼び出しにおいて、メソッド引数は一方向にマーシャリングおよびアンマーシャリングされ、戻り値はもう一方の方向にマーシャリングおよびアンマーシャリングされます。

マーシャリングはすべてのデータ型に適用されますが、インターフェイス ポインターには特別な処理が必要です。根本的な問題は、あるアドレス空間で実行されているクライアント コードが、別のアドレス空間に存在するオブジェクトのインターフェイスへのポインターを、どのようにして正しく参照解決できるかということです。COM の解決策は、クライアント アプリケーションが、クライアントのプロセス内に存在する代理オブジェクト(プロキシ)を通じて元のオブジェクトと通信するというものです。プロキシは元のオブジェクトのインターフェイスへの参照を保持し、クライアントには自身のインターフェイスへのポインターを渡します。クライアントが元のオブジェクトのインターフェイス メソッドを呼び出すと、その呼び出しは実際にはプロキシへ渡されます。したがって、クライアントの観点からは、すべての呼び出しはプロセス内で行われます。

呼び出しを受け取ると、プロキシはメソッド引数をマーシャリングし、RPC などのプロセス間通信の手段を通じて、サーバー プロセス内のコードへ渡します。そのコードは引数をアンマーシャリングして元のオブジェクトへ渡します。この同じコードが、プロキシへ返送するために戻り値をマーシャリングし、プロキシがその値をアンマーシャリングしてクライアント アプリケーションへ渡します。

IMarshal は、クライアント プロセス内でプロキシを作成、初期化、管理するためのメソッドを提供します。ただし、プロキシが元のオブジェクトとどのように通信すべきかは規定しません。IMarshal の COM 既定の実装は RPC を使用します。このインターフェイスを自分で実装する場合は、アプリケーションに適切と考えるプロセス間通信の手段、すなわち共有メモリ、名前付きパイプ、ウィンドウ ハンドル、RPC など、機能するものであれば何でも自由に選択できます。

IMarshal の既定の実装

COM は、独自の実装を提供しないオブジェクトをマーシャリングするために、IMarshal インターフェイスの内部実装を使用します。COM は、オブジェクトに対して IMarshal を照会することでこの判定を行います。インターフェイスが存在しない場合、COM は既定で内部実装を使用します。

IMarshal の COM 既定の実装は、各オブジェクトに対して汎用プロキシを使用し、オブジェクトに実装された各インターフェイスに対して、必要に応じて個別のスタブとプロキシを作成します。この仕組みが必要なのは、特定のオブジェクトがどのインターフェイスを実装しているかを COM が事前に知ることができないためです。COM の既定のマーシャリングを使用せず、代わりに独自のプロキシとマーシャリング ルーチンを記述する開発者は、自身のオブジェクトに存在するすべてのインターフェイスをコンパイル時に把握しているため、必要なマーシャリング コードを正確に理解しています。COM はすべてのオブジェクトに対してマーシャリングのサポートを提供するため、これを実行時に行う必要があります。

インターフェイス プロキシはクライアント プロセスに存在し、インターフェイス スタブはサーバーに存在します。両者は一対となって、そのインターフェイスのすべてのマーシャリングを処理します。各インターフェイス プロキシの役割は、引数をマーシャリングし、以降のインターフェイス呼び出しでやり取りされる戻り値と out パラメーターをアンマーシャリングすることです。各インターフェイス スタブの役割は、関数引数をアンマーシャリングして元のオブジェクトへ渡し、その後、オブジェクトが返す戻り値と out パラメーターをマーシャリングすることです。

プロキシとスタブは、RPC (リモート プロシージャ コール) チャネルを通じて通信します。これはプロセス間通信のためにシステムの RPC インフラストラクチャを利用します。RPC チャネルは単一のインターフェイス IRpcChannelBuffer を実装しており、インターフェイス プロキシとスタブの両方がそのポインターを保持します。プロキシとスタブはこのインターフェイスを呼び出してマーシャリング パケットを取得し、データを相手側へ送信し、完了したらパケットを破棄します。インターフェイス スタブは、元のオブジェクトへのポインターも保持します。

任意のインターフェイスにおいて、プロキシとスタブは同じクラスのインスタンスとして実装されます。このクラスは、システム レジストリ内で ProxyStubClsid32 というラベルの下に各インターフェイスごとに登録されています。このエントリは、インターフェイスの IID をそのプロキシおよびスタブ オブジェクトの CLSID にマッピングします。COM がインターフェイスをマーシャリングする必要がある場合、適切な CLSID を取得するためにシステム レジストリを参照します。この CLSID によって識別されるサーバーは、インターフェイス プロキシとインターフェイス スタブの両方を実装します。

ほとんどの場合、この CLSID が参照するクラスは、あるインターフェイス記述言語で記述された特定インターフェイスの関数シグネチャとセマンティクスの記述を入力とするツールによって自動生成されます。正確さのためにそのような言語を使用することが強く推奨および奨励されますが、必須ではありません。プロキシとスタブは RPC インフラストラクチャで使用される単なる COM コンポーネントであり、そのため、正しい外部契約が守られている限り、任意の方法で記述できます。新しいインターフェイスを設計するプログラマーは、これまでに存在するすべてのインターフェイス プロキシとスタブが、マーシャリングされるデータの表現について合意していることを保証する責任があります。

作成されると、インターフェイス プロキシは常に、オブジェクト全体を表すより大きなプロキシへ集約されます。このオブジェクト プロキシは、プロキシ マネージャーとして知られる COM の汎用プロキシ オブジェクトも集約します。プロキシ マネージャーは、IUnknownIMarshal の 2 つのインターフェイスを実装します。オブジェクトに実装され得る他のすべてのインターフェイスは、個々のインターフェイス プロキシの集約を通じて、そのオブジェクト プロキシ内で公開されます。オブジェクト プロキシへのポインターを保持するクライアントは、実際のオブジェクトへのポインターを保持していると「思い込み」ます。

オブジェクト全体を表すプロキシがクライアント プロセスで必要とされるのは、クライアントがまったく異なるオブジェクトに実装された同一インターフェイスへの呼び出しを区別できるようにするためです。しかし、そのような要件はサーバー プロセスには存在しません。サーバー プロセスにはオブジェクト自体が存在し、すべてのインターフェイス スタブは、それらが作成された対象のオブジェクトとのみ通信するためです。それ以外の接続はあり得ません。

インターフェイス スタブは、インターフェイス プロキシとは対照的に集約されません。外部のクライアントに対して、より大きな全体の一部であるように見せる必要がないためです。接続されると、インターフェイス スタブには、受け取ったメソッド呼び出しの転送先となるサーバー オブジェクトへのポインターが渡されます。特定のオブジェクトのリモート処理を担うサーバー側 RPC インフラストラクチャのコードと状態を指して、概念的にスタブ マネージャーと呼ぶことは有用ですが、そのコードと状態が特定の明確に規定された形式を取るという直接的な要件はありません。

クライアントが特定のオブジェクトのインターフェイスへのポインターを最初に要求すると、COM はサーバー プロセスに IClassFactory スタブをロードし、それを使用して最初のポインターをクライアントへマーシャリングして返します。クライアント プロセスでは、COM はクラス ファクトリ オブジェクトの汎用プロキシをロードし、その IMarshal の実装を呼び出して最初のポインターをアンマーシャリングします。次に COM は最初のインターフェイス プロキシを作成し、RPC チャネルへのポインターを渡します。最後に COM は IClassFactory ポインターをクライアントへ返し、クライアントはそれを使用して IClassFactory::CreateInstance を呼び出し、インターフェイスへの参照を渡します。

サーバー プロセスに戻ると、COM はオブジェクトの新しいインスタンスを、要求されたインターフェイスのスタブとともに作成します。このスタブはインターフェイス ポインターをクライアント プロセスへマーシャリングして返し、そこで今度はオブジェクト自体のための別のオブジェクト プロキシが作成されます。また、要求されたインターフェイスのプロキシも作成され、そのポインターがクライアントへ返されます。オブジェクトの他のインターフェイスへの以降の呼び出しでは、COM は必要に応じて適切なインターフェイス スタブとプロキシをロードします。

新しいインターフェイス プロキシが作成されると、COM はそれに、プロキシ マネージャーの IUnknown 実装へのポインターを渡します。インターフェイス プロキシはすべての QueryInterface 呼び出しをそれに委譲します。各インターフェイス プロキシは、自身が表すインターフェイスと IRpcProxyBuffer という 2 つのインターフェイスを独自に実装します。インターフェイス プロキシは自身のインターフェイスをクライアントに直接公開し、クライアントはプロキシ マネージャーで QueryInterface を呼び出すことでそのポインターを取得できます。ただし、IRpcProxyBuffer を呼び出せるのは COM のみであり、これはプロキシを RPC チャネルへ接続および切断するために使用されます。クライアントはインターフェイス プロキシに照会して IRpcProxyBuffer インターフェイスへのポインターを取得することはできません。

サーバー側では、各インターフェイス スタブが IRpcStubBuffer を実装します。スタブ マネージャーとして機能するサーバー コードは IRpcStubBuffer::Connect を呼び出し、インターフェイス スタブに対象オブジェクトの IUnknown ポインターを渡します。

インターフェイス プロキシがメソッド呼び出しを受け取ると、IRpcChannelBuffer::GetBuffer の呼び出しを通じて、その RPC チャネルからマーシャリング パケットを取得します。引数のマーシャリング処理により、データがバッファーへコピーされます。マーシャリングが完了すると、インターフェイス プロキシは IRpcChannelBuffer::SendReceive を呼び出して、マーシャリングされたパケットを対応するインターフェイス スタブへ送信します。IRpcChannelBuffer::SendReceive が戻ると、引数がマーシャリングされたバッファーは、インターフェイス スタブからマーシャリングされた戻り値を含む新しいバッファーに置き換えられています。インターフェイス プロキシは戻り値をアンマーシャリングし、IRpcChannelBuffer::FreeBuffer を呼び出してバッファーを解放し、その後、戻り値をメソッドの元の呼び出し元へ返します。

要求をサーバー プロセスへ実際に送信し、サーバー プロセスおよびそのプロセス内で要求の送信先となるオブジェクトを識別する方法を知っているのは、IRpcChannelBuffer::SendReceive の実装です。チャネルの実装はまた、そのプロセス内の適切なスタブ マネージャーへ要求を転送する方法も知っています。インターフェイス スタブは、提供されたバッファーから引数をアンマーシャリングし、サーバー オブジェクトの指定されたメソッドを呼び出し、IRpcChannelBuffer::GetBuffer の呼び出しによって割り当てられた新しいバッファーへ戻り値をマーシャリングして返します。次にチャネルは、戻りデータ パケットをインターフェイス プロキシへ送信します。インターフェイス プロキシはまだ IRpcChannelBuffer::SendReceive の途中にあり、それがインターフェイス プロキシへ戻ります。

インターフェイス プロキシの特定のインスタンスは、次の条件が満たされている限り、複数のインターフェイスの処理に使用できます。

インターフェイス スタブの単一のインスタンスも複数のインターフェイスを処理できますが、それはそのインターフェイスの集合が厳密な単一継承関係を持つ場合に限られます。この制限が存在するのは、スタブがどのメソッドがどのインターフェイスに実装されているかを事前に知っている場合にのみ、複数のインターフェイスへメソッド呼び出しを振り分けられるためです。

さまざまな時点で、プロキシとスタブはメモリの割り当てや解放を必要とします。たとえば、インターフェイス プロキシは、呼び出し元へ out パラメーターを返すためのメモリを割り当てる必要があります。この点において、インターフェイス プロキシとインターフェイス スタブは通常の COM コンポーネントにすぎず、標準のタスク アロケーターを使用する必要があります。(CoGetMalloc を参照してください。)

メソッド 6

vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。

vtbl 3 HRESULT GetUnmarshalClass(GUID* riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, GUID* pCid)
riidGUID*inマーシャリングするインターフェイスの GUID(IID)を指定する。
pvvoid*inoptionalマーシャリング対象のインターフェイスポインタを指定する。NULL も指定できる。
dwDestContextDWORDinマーシャリング先の実行コンテキスト(MSHCTX 値)を指定する。
pvDestContextvoid*optional宛先コンテキストに関する予約済みパラメータであり、NULL を指定する。
mshlflagsDWORDinマーシャリングの目的を示すフラグ(MSHLFLAGS 値)を指定する。
pCidGUID*outアンマーシャリングに使用するプロキシクラスの CLSID を受け取る。
vtbl 4 HRESULT GetMarshalSizeMax(GUID* riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, DWORD* pSize)
riidGUID*inマーシャリングするインターフェイスの GUID(IID)を指定する。
pvvoid*inoptionalマーシャリング対象のインターフェイスポインタを指定する。NULL も指定できる。
dwDestContextDWORDinマーシャリング先の実行コンテキスト(MSHCTX 値)を指定する。
pvDestContextvoid*optional宛先コンテキストに関する予約済みパラメータであり、NULL を指定する。
mshlflagsDWORDinマーシャリングの目的を示すフラグ(MSHLFLAGS 値)を指定する。
pSizeDWORD*outマーシャルデータの格納に必要なバイト数の最大値を受け取る。
vtbl 5 HRESULT MarshalInterface(IStream* pStm, GUID* riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags)

IMarshal::MarshalInterface (objidlbase.h) メソッドは、インターフェイス ポインターをマーシャリングします。

pStmIStream*inマーシャリング中に使用されるストリームへのポインター。
riidGUID*inマーシャリングするインターフェイスの識別子への参照。このインターフェイスは IUnknown インターフェイスから派生している必要があります。
pvvoid*inoptionalマーシャリングするインターフェイス ポインターへのポインター。呼び出し元が目的のインターフェイスへのポインターを持っていない場合、このパラメーターは NULL にできます。
dwDestContextDWORDin指定されたインターフェイスがアンマーシャリングされる宛先コンテキスト。dwDestContext に指定可能な値は、列挙体 MSHCTX に由来します。現在、アンマーシャリングは、現在のプロセスの別のアパートメント内 (MSHCTX_INPROC)、または現在のプロセスと同じコンピューター上の別のプロセス内 (MSHCTX_LOCAL) のいずれかで行われます。
pvDestContextvoid*optionalこのパラメーターは予約されており、0 でなければなりません。
mshlflagsDWORDinマーシャリングするデータをクライアント プロセスへ送信し戻すか(典型的なケース)、または複数のクライアントが取得できるグローバル テーブルへ書き込むかを示します。指定可能な値は MSHLFLAGS 列挙体に由来します。

戻り値

このメソッドは、標準の戻り値 E_FAIL のほか、以下の値を返すことができます。

戻り値コード 説明
S_OK
インターフェイス ポインターが正常にマーシャリングされました。
E_NOINTERFACE
指定されたインターフェイスはサポートされていません。
STG_E_MEDIUMFULL
ストリームがいっぱいです。

解説(Remarks)

このメソッドは、CoMarshalInterface の呼び出しにおいて、オブジェクトのインターフェイスへのポインターのマーシャリングを担当するサーバー プロセス内のコードによって間接的に呼び出されます。このマーシャリング コードは通常、まったく異なるオブジェクトに実装されたインターフェイスへのポインターをマーシャリングできる複数のインターフェイスのいずれかに対して、COM が生成するスタブです。例として、IClassFactory インターフェイスや IOleItemContainer インターフェイスが挙げられます。説明のため、ポインターのマーシャリングを担当するコードをマーシャリング スタブと呼びます。

呼び出し元への注意

通常、MarshalInterface を直接呼び出すのではなく、マーシャリング スタブは代わりに、このメソッドの呼び出しを含む CoMarshalInterface 関数を呼び出すべきです。スタブはこの呼び出しによって、オブジェクトにマーシャリング データをストリームへ書き込むよう指示します。その後、スタブはマーシャリング データをクライアント プロセスへ返すか、複数のクライアントによってアンマーシャリングできるグローバル テーブルへ書き込みます。スタブによる CoMarshalInterface の呼び出しの前には通常、マーシャリング データが書き込まれるストリーム バッファーの最大サイズを取得するために CoGetMarshalSizeMax の呼び出しが行われます。

既存の COM インターフェイスを実装する場合、または Microsoft Interface Definition Language (MIDL) を使用して独自のインターフェイスを定義する場合は、このメソッドを明示的に呼び出しません。いずれの場合も、MIDL が生成するスタブが自動的にこの呼び出しを行います。

MIDL を使用して独自のインターフェイスを定義していない場合は、マーシャリング スタブが直接または間接的にこのメソッドを呼び出す必要があります。スタブの実装は、直前の IMarshal::GetMarshalSizeMax の呼び出しが戻った直後に MarshalInterface を呼び出すべきです。GetMarshalSizeMax が返す値は、マーシャリングされるオブジェクトの内部状態が変化しない間のみ有効であることが保証されているため、MarshalInterface の呼び出しを遅らせると、オブジェクトが当初示されたよりも大きなストリーム バッファーを必要とするリスクが生じます。

呼び出し元がマーシャリングするインターフェイスへのポインターを持っている場合は、効率の観点から、pv パラメーターを使用してそのポインターを渡すべきです。こうすることで、そのようなポインターを使用してプロキシに適した CLSID を判定する実装が、自身に対して QueryInterface を呼び出す必要がなくなります。呼び出し元がマーシャリングするインターフェイスへのポインターを持っていない場合は、NULL を渡すことができます。

実装者への注意

MarshalInterface の実装は、受信側でプロキシを初期化するために必要なあらゆるデータをストリームへ書き込む必要があります。そのようなデータには、マーシャリングするインターフェイスへの参照、データをクライアント プロセスへ返すかグローバル テーブルへ書き込むかを指定する MSHLFLAGS 値、そして名前付きパイプ、ウィンドウへのハンドル、RPC チャネルへのポインターなど、オブジェクトへ接続するために必要なものが含まれます。

実装は、ストリームがすべてのデータを保持できる十分な大きさであると想定すべきではありません。むしろ、STG_E_MEDIUMFULL エラーを適切に処理すべきです。終了する直前に、実装はストリーム内のシーク ポインターを、書き込まれたデータの最後のバイトの直後に位置付けるべきです。

pv パラメーターが NULL で、実装がインターフェイス ポインターを必要とする場合は、現在のオブジェクトに対して QueryInterface を呼び出して取得できます。pv パラメーターは単に効率を向上させるために存在します。

将来新しい宛先コンテキストがサポートされるようになっても MarshalInterface の実装が正しく動作し続けるようにするには、実装が処理しないすべての dwDestContext 値について、マーシャリングを COM の既定の実装に委譲してください。マーシャリングを COM の既定の実装に委譲するには、CoGetStandardMarshal ヘルパー関数を呼び出します。

MSHLFLAGS 列挙体を使用して、呼び出し元は、インターフェイス ポインターを単一のクライアントへマーシャリングして返すか、複数のクライアントによってアンマーシャリングできるグローバル テーブルへ書き込むかを指定できます。同じ初期化データから作成される可能性のある複数のプロキシからの呼び出しをオブジェクトが処理できることを保証する必要があります。

vtbl 6 HRESULT UnmarshalInterface(IStream* pStm, GUID* riid, void** ppv)

IMarshal::UnmarshalInterface (objidlbase.h) メソッドは、インターフェイス ポインターをアンマーシャリングします。

pStmIStream*inインターフェイス ポインターのアンマーシャリング元となるストリームへのポインター。
riidGUID*inアンマーシャリングするインターフェイスの識別子への参照。
ppvvoid**outインターフェイス ポインターを受け取るポインター変数のアドレス。正常に戻ると、*ppv にはアンマーシャリングされたインターフェイスの要求されたインターフェイス ポインターが格納されます。

戻り値

このメソッドは、標準の戻り値 E_FAIL のほか、以下の値を返すことができます。

戻り値コード 説明
S_OK
インターフェイス ポインターが正常にアンマーシャリングされました。
E_NOINTERFACE
指定されたインターフェイスはサポートされていません。

解説(Remarks)

アンマーシャリングが行われるプロセス内の COM ライブラリが、プロキシによるこのメソッドの実装を呼び出します。

呼び出し元への注意

このメソッドを直接呼び出すことはありません。ただし、CoUnmarshalInterface の呼び出しを通じて間接的に呼び出す場合があります。たとえば、スタブを実装している場合、スタブがメソッド呼び出しのパラメーターとしてインターフェイス ポインターを受け取ったときに、実装は CoUnmarshalInterface を呼び出します。

実装者への注意

プロキシの実装は、元のオブジェクトの IMarshal::MarshalInterface の実装によってストリームへ書き込まれたデータを読み取り、そのデータを使用して、マーシャリング スタブが元のオブジェクトの IMarshal::GetUnmarshalClass の実装を呼び出して返された CLSID を持つプロキシ オブジェクトを初期化する必要があります。

適切なインターフェイス ポインターを返すには、プロキシの実装は単に自身に対して QueryInterface を呼び出し、riidppv パラメーターを渡すことができます。ただし、UnmarshalInterface の実装は、別のオブジェクトを作成し、必要であればそのポインターを返すこともできます。

終了する直前に、エラーで終了する場合であっても、実装はストリーム内のシーク ポインターを、読み取ったデータの最後のバイトの直後に位置付け直すべきです。

vtbl 7 HRESULT ReleaseMarshalData(IStream* pStm)

IMarshal::ReleaseMarshalData (objidlbase.h) メソッドは、マーシャリングされたデータ パケットを破棄します。

pStmIStream*in破棄するデータ パケットを含むストリームへのポインター。

戻り値

このメソッドは、標準の戻り値 S_OKE_FAIL のほか、IStream インターフェイスのストリーム アクセス エラーのいずれかを返すことができます。

解説(Remarks)

オブジェクトのマーシャリングされたデータ パケットがクライアント プロセス空間でアンマーシャリングされず、そのパケットが不要になった場合、クライアントはプロキシの IMarshal 実装で ReleaseMarshalData を呼び出して、データ パケットを破棄するようオブジェクトに指示します。この呼び出しは CoReleaseMarshalData 関数内で発生します。データ パケットはオブジェクトへの追加の参照として機能し、データを解放することは、Release を呼び出してインターフェイス ポインターを解放することに似ています。

マーシャリングされたデータ パケットが何らかの理由でクライアント プロセスに到達しない場合、または ReleaseMarshalData がプロキシで正常に再作成されない場合、COM はこのメソッドをオブジェクト自体で呼び出すことができます。

呼び出し元への注意

このメソッドを自分で呼び出す機会はめったにありません。あり得る例外は、IMarshal も実装しているクラス オブジェクトのクラス ファクトリに IMarshal を実装する場合です。この場合、複数のクライアントが取得できるテーブルへオブジェクトをマーシャリングしていたとすると、アンマーシャリング ルーチンの一部として ReleaseMarshalData を呼び出し、各プロキシのデータ パケットを解放することがあります。

実装者への注意

実装がマーシャリングされたデータ パケットに関する状態情報を保存している場合、このメソッドを使用して、pStm によって表されるデータ パケットに関連付けられた状態情報を解放できます。実装はまた、ストリーム内のシーク ポインターをデータの最後のバイトの先へ位置付けるべきです。
vtbl 8 HRESULT DisconnectObject(DWORD dwReserved)

IMarshal::DisconnectObject (objidlbase.h) メソッドは、サーバーがオブジェクトのこのメソッドの実装を呼び出すオブジェクトへのすべての接続を解放します。

dwReservedDWORDinこのパラメーターは予約されており、0 でなければなりません。

戻り値

メソッドが成功した場合、戻り値は S_OK です。それ以外の場合は E_FAIL です。

解説(Remarks)

このメソッドは、プロキシではなくオブジェクトに実装されます。

呼び出し元への注意

このメソッドが呼び出される通常のケースは、エンド ユーザーが、IMarshal を実装する 1 つ以上の実行中オブジェクトを持つ COM サーバーを強制的に閉じたときに発生します。シャットダウンする前に、サーバーは CoDisconnectObject 関数を呼び出して、実行中のすべてのオブジェクトへの外部接続を解放します。ただし、IMarshal を実装する各オブジェクトについては、この関数が DisconnectObject を呼び出すため、自身のマーシャリングを管理する各オブジェクトが、シャットダウンしようとしていることをプロキシへ通知する処理を行えます。

実装者への注意

通常のシャットダウン コードの一部として、サーバーは IMarshal を実装する実行中の各オブジェクトに対して CoDisconnectObject を呼び出すべきです。この関数は次に DisconnectObject を呼び出します。

このメソッドのあらゆる実装の結果は、プロキシがクライアントからの以降のすべての呼び出しに対して、元のオブジェクトへ呼び出しを転送しようとするのではなく、RPC_E_DISCONNECTED または CO_E_OBJNOTCONNECTED を返すことで応答できるようにすることであるべきです。プロキシを破棄するのはクライアントの役割です。

モニカーなどの不変オブジェクトに対してこのメソッドを実装する場合、そのようなオブジェクトは通常、クライアントのアドレス空間へ丸ごとコピーされるため、実装は何もする必要がありません。したがって、それらにはプロキシも元のオブジェクトへの接続も存在しません。不変オブジェクトのマーシャリングの詳細については、IMarshal トピックの「When to Implement」セクションを参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

HSP用 COM定義

#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"

出力引数:
#define global IID_IMarshal "{00000003-0000-0000-C000-000000000046}"
#usecom global IMarshal IID_IMarshal "{}"
#comfunc global IMarshal_GetUnmarshalClass   3 var,sptr,int,sptr,int,var
#comfunc global IMarshal_GetMarshalSizeMax   4 var,sptr,int,sptr,int,var
#comfunc global IMarshal_MarshalInterface    5 sptr,var,sptr,int,sptr,int
#comfunc global IMarshal_UnmarshalInterface  6 sptr,var,sptr
#comfunc global IMarshal_ReleaseMarshalData  7 sptr
#comfunc global IMarshal_DisconnectObject    8 int
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。
; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。
; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。