相互運用マーシャリング

相互運用マーシャリングでは、メソッド引数と戻り値によって、呼び出し中にマネージドとアンマネージドのメモリ間でデータを受け渡す方法が制御されます。 相互運用マーシャリングは、共通言語ランタイムのマーシャリング サービスによって実行される、ランタイム アクティビティです。

ほとんどのデータ型は、マネージドとアンマネージドの両方のメモリに共通の表現があります。 相互運用マーシャラーは、これらの型を処理します。 その他の型は、あいまいな型であるか、マネージド メモリでまったく表現されていない型である可能性があります。

あいまいな型は、複数のアンマネージド表現が 1 つのマネージド型にマップされていたり、配列のサイズなどの型情報が欠落していたりします。 あいまいな型の場合、マーシャラーは、既定の表現と複数の表現が存在するときのための代替表現とを提供します。 あいまいな型をマーシャリングする方法について、マーシャラーに明示的な指示を与えることができます。

プラットフォーム呼び出しと COM 相互運用のモデル

共通言語ランタイムは、アンマネージ コードと相互運用するために、次の 2 つのメカニズムを提供します。

  • プラットフォーム呼び出しにより、マネージド コードは、アンマネージド ライブラリからエクスポートされた関数を呼び出すことができます。
  • COM 相互運用により、マネージド コードは、インターフェイスを介してコンポーネント オブジェクト モデル (COM) オブジェクトと対話できます。

プラットフォーム呼び出しと COM 相互運用はどちらも、必要な場合に、相互運用マーシャリングを使用して呼び出し元と呼び出し先との間でメソッド引数を正確に移動します。 次の図が示すように、プラットフォーム呼び出しメソッドの呼び出しはマネージド コードからアンマネージド コードにフローして、コールバック関数が関係していない限りその逆の方向にはフローしません。 プラットフォーム呼び出しの呼び出しはマネージド コードからアンマネージド コードにのみフローしますが、データは入出力パラメーターとして双方向にフローできます。 COM 相互運用のメソッド呼び出しは、どちらの方向にもフローできます。

Platform invoke

最下位のレベルでは、どちらのメカニズムも同じ相互運用マーシャリング サービスを使用します。ただし、特定のデータ型は、COM 相互運用またはプラットフォーム呼び出しでのみサポートされます。 詳しくは、「既定のマーシャリング動作」を参照してください。

マーシャリングと COM アパートメント

相互運用マーシャラーは、共通言語ランタイム ヒープとアンマネージド ヒープの間でデータをマーシャリングします。 呼び出し元と呼び出し先がデータの同じインスタンスで機能できないときには常に、マーシャリングが生じます。 相互運用マーシャラーにより、呼び出し元と呼び出し先がデータの独自のコピーを持っている場合でも、見かけ上は同じデータに対して機能しているようにすることが可能になります。

COM には、COM アパートメント間や異なる COM プロセス間でデータをマーシャリングするマーシャラーもあります。 同じ COM アパートメント内でマネージド コードとアンマネージド コード間の呼び出しをする場合は、相互運用マーシャラーが関連する唯一のマーシャラーとなります。 異なる COM アパートメントや異なるプロセス内でマネージド コードとアンマネージド コード間の呼び出しをする場合は、相互運用マーシャラーと COM マーシャラーの両方が関連します。

COM クライアントとマネージド サーバー

Regasm.exe (アセンブリ登録ツール) によって登録されたタイプ ライブラリのあるエクスポートされたマネージド サーバーでは、ThreadingModel レジストリ エントリが Both に設定されています。 この値は、シングルスレッド アパートメント (STA) またはマルチスレッド アパートメント (MTA) で、サーバーをアクティブ化できることを示します。 次の表に示すように、サーバー オブジェクトは、その呼び出し元と同じアパートメント内に作成されます。

COM クライアント .NET サーバー マーシャリングの要件
STA Both は STA になります。 同じアパートメントでのマーシャリング。
MTA Both は MTA になります。 同じアパートメントでのマーシャリング。

クライアントとサーバーが同じアパートメント内にあるため、相互運用マーシャリング サービスはすべてのデータのマーシャリングを自動的に処理します。 次の図は、同じ COM スタイル アパートメント内のマネージドとアンマネージドのヒープ間で機能している、相互運用マーシャリング サービスを示しています。

Interop marshalling between managed and unmanaged heaps

マネージド サーバーをエクスポートする予定の場合は、サーバーのアパートメントが COM クライアントによって決定されることに注意してください。 MTA 内で初期化された COM クライアントから呼び出されるマネージド サーバーは、スレッド セーフを確保する必要があります。

マネージド クライアントと COM サーバー

マネージド クライアントのアパートメントの既定の設定は MTA です。ただし、.NET クライアントのアプリケーションの種類によっては、既定の設定が変更されることがあります。 たとえば、Visual Basic クライアント アパートメントの設定は STA です。 System.STAThreadAttributeSystem.MTAThreadAttributeThread.ApartmentState プロパティ、または Page.AspCompatMode プロパティを使用して、マネージド クライアントのアパートメントの設定を変更できます。

コンポーネントの作成者は、COM サーバーのスレッド アフィニティを設定します。 次の表は、.NET クライアントと COM サーバーのアパートメント設定の組み合わせを示しています。 また、結果として生じる、組み合わせのためのマーシャリング要件も示しています。

.NET クライアント COM サーバー マーシャリングの要件
MTA (既定) MTA

STA
相互運用マーシャリング。

相互運用と COM マーシャリング。
STA MTA

STA
相互運用と COM マーシャリング。

相互運用マーシャリング。

マネージド クライアントとアンマネージド サーバーが同じアパートメント内にあるとき、相互運用マーシャリング サービスはすべてのデータのマーシャリングを処理します。 ただし、クライアントとサーバーが異なるアパートメント内で初期化される場合は、COM マーシャリングも必要となります。 次の図では、アパートメント間の呼び出しの要素を示します。

Cross-apartment call between a .NET client and COM object

アパートメント間のマーシャリングでは、次の操作を実行できます。

  • アパートメント間のマーシャリングのオーバーヘッドを受け入れます。これは、境界を越える呼び出しが多くある場合にのみ認識されます。 呼び出しがアパートメントの境界を正常に越えるようにするためには、COM コンポーネントのタイプ ライブラリを登録する必要があります。

  • クライアント スレッドを STA または MTA に設定して、メイン スレッドを変更します。 たとえば、C# クライアントが多くの STA COM コンポーネントを呼び出す場合には、メイン スレッドを STA に設定してアパートメント間のマーシャリングを回避できます。

    Note

    C# クライアントのスレッドを STA に設定すると、MTA COM コンポーネントへの呼び出しにはアパートメント間のマーシャリングが必要となります。

アパートメント モデルを明示的に選択する方法については、「マネージドとアンマネージド スレッド」を参照してください。

リモートの呼び出しのマーシャリング

アパートメント間のマーシャリングの場合と同様に、COM マーシャリングは、オブジェクトが別個のプロセス内に存在するときには常に、マネージドとアンマネージドのコード間の各呼び出しに関与します。 次に例を示します。

  • リモート ホスト上のマネージド サーバーを呼び出す COM クライアントは、分散 COM (DCOM) を使用します。
  • リモート ホスト上の COM サーバーを呼び出すマネージド クライアントは、DCOM を使用します。

次の図では、相互運用マーシャリングと COM マーシャリングにより、プロセスとホストの境界を越えて通信チャネルが提供される方法を示します。

Cross-process marshalling

ID の保持

共通言語ランタイムは、マネージド参照とアンマネージド参照の ID を保持します。 次の図は、プロセスとホストの境界を越えている、直接アンマネージド参照 (上の行) と直接マネージド参照 (下の行) のフローを示しています。

COM callable wrapper and runtime callable wrapper

この図では:

  • アンマネージド クライアントは、COM オブジェクトへの参照を、リモート ホストからその参照を取得するマネージド オブジェクトから取得します。 リモート処理のメカニズムは DCOM です。

  • マネージド クライアントは、マネージド オブジェクトへの参照を、リモート ホストからその参照を取得している COM オブジェクトから取得します。 リモート処理のメカニズムは DCOM です。

    Note

    マネージド サーバーのエクスポート済みタイプ ライブラリを登録する必要があります。

呼び出し元と呼び出し先の間のプロセス境界の数は関連していません。同じ直接参照が、イン プロセスおよびアウト プロセスの呼び出しで発生します。

マネージド リモート処理

ランタイムは、プロセスとホストの境界を越えてマネージド オブジェクト間に通信チャネルを確立するために使用できる、マネージド リモート処理も提供します。 次の図に示すように、マネージド リモート処理は、通信コンポーネントの間のファイアウォールに対応できます。

SOAP or TcpChannel SOAP または TcpChannel クラスを使用するファイアウォールを越えたリモート呼び出し

サービス コンポーネントと COM の間の呼び出しなど、一部のアンマネージド呼び出しは SOAP を介して伝達できます。

Title 説明
既定のマーシャリングの動作 相互運用マーシャリング サービスがデータのマーシャリングに使用する規則について説明します。
プラットフォーム呼び出しによるデータのマーシャリング メソッドのパラメーターを宣言してアンマネージ ライブラリによってエクスポートされた関数に引数を渡す方法について説明します。
COM 相互運用機能によるデータのマーシャリング COM ラッパーをカスタマイズしてマーシャリング動作を変更する方法について説明します。
方法: マネージド コード DCOM を WCF に移行する DCOM から WCF に移行する方法について説明します。
方法: HRESULT に例外を割り当てる HRESULT にカスタム例外をマップする方法について説明し、各 HRESULT から .NET Framework での同等の例外クラスへの完全なマッピングを示します。
ジェネリック型を使用する相互運用 COM 相互運用性のジェネリック型を使用するとき、どのアクションがサポートされるかについて説明します。
アンマネージ コードとの相互運用 共通言語ランタイムが提供する相互運用サービスについて説明します。
高度な COM 相互運用性 .NET Framework アプリケーションに COM コンポーネントを組み込む方法についての詳細情報へのリンクを示します。
相互運用のためのデザインの考慮事項 統合 COM コンポーネントを記述するためのヒントを示します。

関連項目

System.Runtime.InteropServices