IMarshal インターフェイス (objidlbase.h)

COM オブジェクトがインターフェイス ポインターのマーシャリングを定義および管理できるようにします。

継承

IMarshal インターフェイスは、IUnknown インターフェイスから継承されます。 IMarshal には、次の種類のメンバーもあります。

メソッド

IMarshal インターフェイスには、これらのメソッドがあります。

 
IMarshal::D isconnectObject

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

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

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

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

注釈

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

マーシャリングはすべてのデータ型に適用されますが、インターフェイス ポインターには特別な処理が必要です。 基本的な問題は、1 つのアドレス空間で実行されているクライアント コードが、異なるアドレス空間に存在するオブジェクト上のインターフェイスへのポインターを正しく逆参照する方法です。 COM ソリューションは、クライアント アプリケーションが、クライアントのプロセスに含まれるサロゲート オブジェクトまたはプロキシを介して元のオブジェクトと通信することです。 プロキシは、元のオブジェクトのインターフェイスへの参照を保持し、クライアント自体のインターフェイスへのポインターをクライアントに提供します。 クライアントが元のオブジェクトでインターフェイス メソッドを呼び出すと、その呼び出しは実際にはプロキシに送信されます。 したがって、クライアントの観点からは、すべての呼び出しが処理中です。

呼び出しを受信すると、プロキシはメソッド引数をマーシャリングし、RPC などの何らかのプロセス間通信を介してそれらをサーバー プロセスのコードに渡します。これにより、引数のマーシャリングが解除され、元のオブジェクトに渡されます。 この同じコードは、プロキシへの転送の戻り値をマーシャリングし、値のマーシャリングを解除してクライアント アプリケーションに渡します。

IMarshal には、クライアント プロセスでプロキシを作成、初期化、管理するためのメソッドが用意されています。プロキシが元のオブジェクトと通信する方法は指定されません。 IMarshal の COM の既定の実装では、RPC が使用されます。 このインターフェイスを自分で実装すると、アプリケーションに適していると思われるプロセス間通信の任意の方法 (共有メモリ、名前付きパイプ、ウィンドウ ハンドル、RPC) を自由に選択できます。要するに、動作するものは何でもかまいません。

IMarshal の既定の実装

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

IMarshal の COM の既定の実装では、オブジェクトごとに汎用プロキシが使用され、オブジェクトに実装されているインターフェイスごとに、必要に応じて個々のスタブとプロキシが作成されます。 特定のオブジェクトが実装できる特定のインターフェイスを COM が事前に認識できないため、このメカニズムが必要です。 COM の既定のマーシャリングを使用せず、代わりに独自のプロキシおよびマーシャリング ルーチンを記述することを選択する開発者は、コンパイル時にすべてのインターフェイスをオブジェクトで検出し、マーシャリング コードが必要な内容を正確に理解します。 COM は、すべてのオブジェクトのマーシャリング サポートを提供する際に、実行時にこれを行う必要があります。

インターフェイス プロキシはクライアント プロセスに存在します。インターフェイス スタブはサーバーに存在します。 一緒に、各ペアはインターフェイスのすべてのマーシャリングを処理します。 各インターフェイス プロキシのジョブは、引数をマーシャリングし、そのインターフェイスへの後続の呼び出しで前後に渡される戻り値と out パラメーターをマーシャリングすることです。 各インターフェイス スタブのジョブは、関数引数のマーシャリングを解除し、それらを元のオブジェクトに渡してから、オブジェクトが返す戻り値と out パラメーターをマーシャリングすることです。

プロキシとスタブは、システムの RPC インフラストラクチャをプロセス間通信に利用する RPC (リモート プロシージャ コール) チャネルを使用して通信します。 RPC チャネルは、インターフェイス プロキシとスタブの両方がポインターを保持する 1 つのインターフェイス 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 呼び出しを委任します。 各インターフェイス プロキシは、それ自体の 2 つのインターフェイス (それが表すインターフェイスと IRpcProxyBuffer) を実装します。 インターフェイス プロキシは、独自のインターフェイスをクライアントに直接公開します。このインターフェイスは、プロキシ マネージャーで QueryInterface を 呼び出すことによってポインターを取得できます。 ただし、プロキシを RPC チャネルに接続して切断するために使用される IRpcProxyBuffer を呼び出すことができるのは COM だけです。 クライアントはインターフェイス プロキシに対してクエリを実行して 、IRpcProxyBuffer インターフェイスへのポインターを取得できません。

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

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

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

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

  • 影響を受けるインターフェイスの ID は、システム レジストリ内の適切な ProxyStubClsid にマップする必要があります。
  • インターフェイス プロキシは、サポートされているインターフェイスから他のインターフェイスへの QueryInterface の呼び出しを通常どおりサポートし、 IUnknownIRpcProxyBuffer からの呼び出しをサポートする必要があります。
インターフェイス スタブの 1 つのインスタンスは、複数のインターフェイスにサービスを提供することもできますが、その一連のインターフェイスに厳密な単一継承関係がある場合に限られます。 スタブは、どのメソッドがどのインターフェイスに実装されているかを事前に認識している場合にのみ、複数のインターフェイスにメソッド呼び出しを送信できるため、この制限が存在します。

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

要件

要件
サポートされている最小のクライアント Windows 2000 Professional [デスクトップ アプリ |UWP アプリ]
サポートされている最小のサーバー Windows 2000 Server [デスクトップ アプリ |UWP アプリ]
対象プラットフォーム Windows
ヘッダー objidlbase.h (ObjIdl.h を含む)

こちらもご覧ください

IStdMarshalInfo