Inter-Object 通信
COM は、オブジェクトが実行されている場所 (同じプロセス、同じコンピューター、または別のコンピューター) に関係なく、クライアントがオブジェクトと透過的に通信できるように設計されています。 これにより、すべての種類のオブジェクトと、オブジェクト クライアントとオブジェクト サーバーの両方に対して、単一のプログラミング モデルが提供されます。
クライアントの観点からは、すべてのオブジェクトはインターフェイス ポインターを介してアクセスされます。 ポインターはインプロセスである必要があります。 実際、インターフェイス関数の呼び出しは常に、最初にインプロセス コードの一部に到達します。 オブジェクトが処理中の場合、呼び出しはシステム インフラストラクチャ コードを介在させず、直接呼び出しに到達します。 オブジェクトがアウトプロセスの場合、呼び出しは、COM またはオブジェクト (実装者が望む場合) によって提供される "プロキシ" オブジェクトと呼ばれるものに最初に到達します。 プロキシ パッケージはパラメーター (インターフェイス ポインターを含む) を呼び出し、オブジェクト実装が配置されている他のプロセスまたは他のコンピューターに適切なリモート プロシージャ コール (またはカスタム生成プロキシの場合は他の通信メカニズム) を生成します。 プロセス境界を越えた伝送のためにポインターをパッケージ化するこのプロセスは、マーシャリング 呼ばれます。
サーバーの観点からは、オブジェクトのインターフェイス関数へのすべての呼び出しは、そのインターフェイスへのポインターを介して行われます。 ここでも、ポインターは 1 つのプロセス内でのみコンテキストを持ち、呼び出し元は常にインプロセス コードの一部である必要があります。 オブジェクトが処理中の場合、呼び出し元はクライアント自体です。 それ以外の場合、呼び出し元は COM またはオブジェクト自体によって提供される "スタブ" オブジェクトです。 スタブは、クライアント プロセスの "proxy" からリモート プロシージャ コール (またはカスタム生成プロキシの場合は他の通信メカニズム) を受け取り、パラメーターのマーシャリングを解除し、サーバー オブジェクト上の適切なインターフェイスを呼び出します。 クライアントとサーバーの両方の観点から、常に他のインプロセス コードと直接通信します。
COM は、標準マーシャリングと呼ばれるマーシャリングの実装を提供します。 この実装はほとんどのオブジェクトに対して非常に適切に機能し、プログラミング要件を大幅に削減し、マーシャリング プロセスを効果的に透過的にします。
ただし、COM のプロセスの透明性の実装からインターフェイスを明確に分離すると、状況によっては邪魔になる可能性があります。 クライアントの観点からその機能に焦点を当てたインターフェイスの設計は、ネットワーク全体でそのインターフェイスの効率的な実装と競合する設計上の決定につながる場合があります。 このような場合、必要なのは純粋なプロセスの透明性ではなく、「注意する必要がない限り、プロセスの透明性」です。COM では、オブジェクト実装者がカスタム マーシャリング (IMarshal マーシャリングとも呼ばれます) をサポートできるようにすることで、この機能を提供します。 標準的なマーシャリングは、実際にはカスタム マーシャリングのインスタンスです。これは、オブジェクトがカスタム マーシャリングを必要としない場合に使用される既定の実装です。
カスタム マーシャリングを実装して、オブジェクトがネットワーク経由で使用される場合と、ローカル アクセスでクライアントに対して完全に透過的である場合とは異なるアクションを実行できるようにします。 このアーキテクチャにより、ネットワーク パフォーマンスの問題に関係なくクライアント/オブジェクト インターフェイスを設計し、後で確立された設計を中断することなくネットワーク パフォーマンスの問題に対処できます。
COM では、コンポーネントの構造化方法は指定されていません。それは、それらがどのように相互作用するかを指定します。 COM は、コンポーネントの内部構造に関する懸念事項をプログラミング言語と開発環境に残します。 逆に、プログラミング環境には、即時アプリケーションの外部でオブジェクトを操作するための標準が設定されていません。 たとえば、Microsoft Visual C++ は、アプリケーション内のオブジェクトを操作する場合に非常に適していますが、アプリケーションの外部のオブジェクトを操作することはできません。 一般に、この点で他のすべてのプログラミング言語は同じです。 そのため、ネットワーク全体の相互運用性を提供するために、COM は言語に依存しないインターフェイスを介して、プログラミング言語が終了する場所を選択します。
vtbl 構造体の二重間接参照は、関数ポインターのテーブル内のポインターが、実際のオブジェクト内の実際の実装を直接指す必要はないことを意味します。 これがプロセスの透明性の中核です。
オブジェクトがクライアント プロセスに直接読み込まれるインプロセス サーバーの場合、関数はテーブル内のポインターを実際の実装に直接ポイントします。 この場合、クライアントからインターフェイス メソッドへの関数呼び出しによって、実行制御がメソッドに直接転送されます。 ただし、メモリへのポインターはプロセス間で共有できないため、これはリモートオブジェクトだけでなくローカルオブジェクトでも機能しません。 ただし、クライアントは、実際の実装を呼び出しているかのようにインターフェイス メソッドを呼び出すことができる必要があります。 したがって、クライアントは、呼び出しを行うことによって、一部のオブジェクト内のメソッドに制御を一様に転送します。
クライアントは常に、一部のインプロセス オブジェクトでインターフェイス メソッドを呼び出します。 実際のオブジェクトがローカルまたはリモートの場合、プロキシ オブジェクトへの呼び出しが行われ、その後、実際のオブジェクトへのリモート プロシージャ呼び出しが行われます。
では、実際に実行されるメソッドは何でしょうか。 答えは、アウトプロセス インターフェイスの呼び出しが発生するたびに、各インターフェイス メソッドがプロキシ オブジェクトによって実装されるということです。 プロキシ オブジェクトは常に、呼び出されるオブジェクトに代わって動作するインプロセス オブジェクトです。 このプロキシ オブジェクトは、実際のオブジェクトがローカル サーバーまたはリモート サーバーで実行されていることを認識します。
プロキシ オブジェクトは、関数パラメーターを一部のデータ パケットにパッケージし、ローカル オブジェクトまたはリモート オブジェクトへの RPC 呼び出しを生成します。 そのパケットは、ローカル コンピューターまたはリモート コンピューター上のサーバーのプロセス内のスタブ オブジェクトによって取得されます。これにより、パラメーターがアンパックされ、メソッドの実際の実装が呼び出されます。 その関数が戻ると、スタブは出力パラメーターと戻り値をパッケージし、プロキシに送り返します。この関数は、それらをアンパックして元のクライアントに返します。
したがって、クライアントとサーバーは常に、すべてが処理中であるかのように相互に通信します。 クライアントからの呼び出しとサーバーへのすべての呼び出しは、ある時点でインプロセスです。 ただし、vtbl 構造体を使用すると、COM などの一部のエージェントですべての関数呼び出しをインターセプトし、関数からすべての戻り値を受け取ることができるため、そのエージェントは必要に応じてそれらの呼び出しを RPC 呼び出しにリダイレクトできます。 インプロセス呼び出しはアウトプロセス呼び出しよりも高速ですが、プロセスの違いはクライアントとサーバーに対して完全に透過的です。
詳細については、次のトピックを参照してください。
関連トピック