マネージ/アンマネージ コードの相互運用性の概要

 

Sonja Keserovic プログラム マネージャー
David Mortenson、リード ソフトウェア デザイン エンジニア
Adam Nathan、テストのリード ソフトウェア デザイン エンジニア

Microsoft Corporation

2003 年 10 月

適用対象:
   Microsoft® .NET Framework
   COM 相互運用

概要: この記事では、マネージド コードとアンマネージド コードの相互運用性に関する基本的な事実と、マネージド コードからアンマネージド API にアクセスしてラップしたり、マネージド API をアンマネージド呼び出し元に公開したりするためのガイドラインと一般的なプラクティスについて説明します。 セキュリティと信頼性に関する考慮事項、パフォーマンス データ、開発プロセスの一般的なプラクティスも強調されています。 (14ページ印刷)

前提 条件: このドキュメントの対象ユーザーには、マネージド コードを使用する場所について大まかな決定を行う必要がある開発者とマネージャーが含まれます。 そのためには、マネージド コードとアンマネージド コード間の相互作用のしくみと、現在のガイドラインが特定のシナリオにどのように適用されるかを理解すると役立ちます。

内容

相互運用性の概要
相互運用性のガイドライン
セキュリティ
[信頼性]
パフォーマンス
付録 1: 相互運用性境界を越える
付録 2: リソース
付録 3: 用語集

相互運用性の概要

共通言語ランタイム (CLR) は、COM コンポーネント、COM+ サービス、Win32® API、およびその他の種類のアンマネージ コードとのマネージ コードの相互作用を促進します。 データ型、エラー処理メカニズム、作成ルールと破棄規則、および設計ガイドラインは、マネージド オブジェクト モデルとアンマネージド オブジェクト モデルによって異なります。 マネージド コードとアンマネージド コード間の相互運用を簡略化し、移行パスを容易にするために、CLR 相互運用レイヤーは、クライアントとサーバーの両方からこれらのオブジェクト モデル間の違いを隠します。

相互運用性 ("相互運用") は双方向であるため、次のことが可能になります。

  • マネージド コードからアンマネージ API を呼び出す

    これは、フラット API (kernel32.dllやuser32.dllなどの DLL から公開される Win32 API などの静的 DLL エクスポート) と COM API (Microsoft® Word、Excel、インターネット エクスプローラー、ActiveX® データ オブジェクト (ADO) によって公開されるオブジェクト モデルなど) の両方に対して実行できます。

  • マネージド API をアンマネージド コードに公開する

    これを行う例としては、Windows Media® Player などの COM ベースのアプリケーション用のアドインを作成したり、MFC フォームにマネージド Windows フォーム コントロールを埋め込んだりします。

次の 3 つの補完的なテクノロジを使用すると、次のマネージド/アンマネージド対話を実現できます。

  • プラットフォーム呼び出し (P/Invoke とも呼ばれます) を使用すると、マネージド ソース コードでシグネチャが再宣言されている限り、アンマネージ言語で任意の関数を呼び出すことができます。 これは、Visual Basic® 6.0 の ステートメントによって Declare 提供された機能に似ています。
  • COM 相互運用機能を使用すると、通常のマネージド コンポーネントの使用と同様の方法で、任意のマネージド言語で COM コンポーネントを呼び出すことができます。その逆も可能です。 COM 相互運用機能は、CLR によって提供されるコア サービスと、 System.Runtime.InteropServices 名前空間の一部のツールと API で構成されます。
  • C++ 相互運用機能 (It Just Works (IJW) とも呼ばれます) は C++固有の機能であり、フラット API と COM API は常に使用されているため、直接使用できます。 これは COM 相互運用よりも強力ですが、より多くの注意が必要です。 このテクノロジを使用する前に、必ず C++ リソースをチェックしてください。

相互運用性のガイドライン

マネージド コードからのアンマネージ API の呼び出し

アンマネージド API にはいくつかの種類があり、それらを呼び出すための相互運用テクノロジにはいくつかの種類があります。 これらのテクノロジを使用する方法とタイミングに関する提案については、このセクションで説明します。 これらの提案は非常に一般的であり、すべてのシナリオをカバーしているわけではないことに注意してください。 シナリオを慎重に評価し、シナリオに適した開発プラクティスやソリューションを適用する必要があります。

アンマネージ フラット API の呼び出し

マネージド コードからアンマネージド フラット API を呼び出すには、プラットフォーム呼び出し (すべてのマネージド言語で利用可能) または C++ 相互運用 (C++ で利用可能) の 2 つのメカニズムがあります。

これらの相互運用テクノロジのいずれかを使用してフラット API を呼び出す前に、.NET Frameworkで使用可能な同等の機能があるかどうかを判断する必要があります。 可能な限り、アンマネージド API を呼び出す代わりに.NET Framework機能を使用することをお勧めします。

少数のアンマネージ メソッドを呼び出す場合や、単純なフラット API を呼び出す場合は、C++ 相互運用ではなくプラットフォーム呼び出しを使用することをお勧めします。 単純なフラット API のプラットフォーム呼び出し宣言の記述は簡単です。 CLR は、DLL の読み込みとすべてのパラメーター マーシャリングを処理します。 複雑なフラット API に対していくつかのプラットフォーム呼び出し宣言を記述する作業も、C++ 相互運用機能を使用し、C++ で記述されたまったく新しいモジュールを導入するコストと比べるとごくわずかです。

複雑なアンマネージド フラット API をラップする場合や、マネージド コードの開発中に変更されるアンマネージ フラット API をラップする場合は、プラットフォーム呼び出しの代わりに C++ 相互運用機能を使用することをお勧めします。 C++ レイヤーは非常に薄くすることができ、マネージド コードの残りの部分は任意の他のマネージド言語で記述できます。 これらのシナリオでプラットフォーム呼び出しを使用するには、マネージ コードで API の複雑な部分を再宣言し、それらをアンマネージド API と同期させるために多くの労力が必要になります。 C++ 相互運用機能を使用すると、アンマネージド API への直接アクセスを許可することで、この問題を解決できます。これは、ヘッダー ファイルを含めるだけで書き換える必要はありません。

COM API の呼び出し

マネージド コードから COM コンポーネントを呼び出すには、COM 相互運用機能 (すべてのマネージド言語で利用可能) または C++ 相互運用機能 (C++ で使用可能) の 2 つの方法があります。

OLE オートメーション互換 COM コンポーネントを呼び出す場合は、COM 相互運用機能を使用することが推奨されます。 CLR は、COM コンポーネントのアクティブ化とパラメーター マーシャリングを処理します。

インターフェイス定義言語 (IDL) に基づいて COM コンポーネントを呼び出す場合は、C++ 相互運用機能を使用することが推奨されます。 C++ レイヤーは非常に薄くすることができ、マネージド コードの残りの部分は任意のマネージド言語で記述できます。 COM 相互運用機能は、タイプ ライブラリからの情報に依存して正しい相互運用呼び出しを行いますが、通常、タイプ ライブラリには IDL ファイルに存在するすべての情報が含まれているわけではありません。 C++ 相互運用機能を使用すると、これらの COM API への直接アクセスを許可することで、この問題が解決されます。

既に出荷済みの COM API を所有する企業では、これらの API のプライマリ相互運用機能アセンブリ (PIA) を出荷することを検討することが重要であるため、マネージド クライアントで簡単に使用できます。

アンマネージド API を呼び出すためのデシジョン ツリー

図 1. アンマネージ API デシジョン ツリーの呼び出し

マネージド API をアンマネージド コードに公開する

マネージド API を純粋にアンマネージドの呼び出し元に公開するには、COM API またはフラット API の 2 つのメイン方法があります。 Visual Studio® .NET を使用してコードを再コンパイルする C++ アンマネージド クライアントの場合、3 つ目のオプションは、C++ 相互運用を介してマネージド機能に直接アクセスすることです。 これらのオプションを使用する方法とタイミングに関する推奨事項については、このセクションで説明します。

マネージド API への直接アクセス

アンマネージド クライアントが C++ で記述されている場合は、Visual Studio .NET C++ コンパイラを使用して "混合モード イメージ" としてコンパイルできます。これが完了すると、アンマネージド クライアントは任意のマネージド API に直接アクセスできます。 ただし、一部のコーディング規則は、アンマネージド コードからマネージド オブジェクトにアクセスする場合に適用されます。詳細については、C++ のドキュメントをチェックします。

直接アクセスは、マネージド API 開発者からの特別な考慮事項を必要としないため、推奨されるオプションです。 マネージド API 設計ガイドライン (DG) に従ってマネージド API を設計し、アンマネージド呼び出し元が API に引き続きアクセスできることを確信できます。

マネージ API を COM API として公開する

すべてのパブリック マネージド クラスは、COM 相互運用機能を使用してアンマネージド クライアントに公開できます。 COM 相互運用層がすべての COM プラミングを処理するため、このプロセスは実装が非常に簡単です。 したがって、たとえば、すべてのマネージド クラスは、 IUnknownIDispatchISupportErrorInfo、およびその他のいくつかの標準 COM インターフェイスを実装しているように見えます。

マネージド API を COM API として公開するのは簡単ですが、マネージド オブジェクト モデルと COM オブジェクト モデルは大きく異なります。 そのため、マネージ API を COM に公開することは、常に明示的な設計上の決定である必要があります。 マネージド ワールドで使用できる一部の機能は、COM の世界では同等ではなく、COM クライアントからは使用できません。 このため、多くの場合、マネージド API 設計ガイドライン (DG) と COM との互換性には緊張があります。

COM クライアントが重要な場合は、マネージド API の設計ガイドラインに従ってマネージド API を記述し、COM に公開されるマネージド API の周囲に、COM 対応のシン マネージド ラッパーを記述します。

マネージド API をフラット API として公開する

アンマネージ クライアントで COM を使用できない場合があります。 たとえば、フラット API を使用するように既に記述されており、変更または再コンパイルすることはできません。 C++ は、マネージド API をフラット API として公開できる唯一の高レベル言語です。 これを行うことは、COM API としてマネージド API を公開するほど簡単ではありません。 これは、C++ 相互運用の高度な知識と、マネージドワールドとアンマネージドワールドの違いを必要とする非常に高度な手法です。

絶対に必要な場合にのみ、マネージド API をフラット API として公開します。 選択肢がない場合は、C++ のドキュメントをチェックし、すべての制限事項を十分に認識してください。

マネージド API を公開するためのデシジョン ツリー

図 2. マネージド API デシジョン ツリーの公開

セキュリティ

共通言語ランタイムには、アセンブリの原点に関する情報に基づいて保護されたリソースへのアクセスを規制するセキュリティ システム Code Access Security (CAS) が付属しています。 アンマネージド コードを呼び出すと、大きなセキュリティ リスクが発生します。 適切なセキュリティ チェックがないと、アンマネージ コードは CLR プロセス内のマネージド アプリケーションの任意の状態を操作できます。 また、これらのリソースが CAS アクセス許可チェックの対象とならずに、アンマネージ コード内のリソースを直接呼び出すこともできます。 そのため、アンマネージド コードへの移行は高度に保護された操作と見なされ、セキュリティ チェックを含める必要があります。 このセキュリティ チェックは、アンマネージド コード遷移を含むアセンブリと、それを呼び出すすべてのアセンブリが、アンマネージ コードを実際に呼び出す権限を持つ必要があるアンマネージ コードアクセス許可を検索します。

完全なセキュリティ チェックが不要であり、コンポーネントのパフォーマンスまたはスコープを過度に制限する、いくつかの制限付き相互運用シナリオがあります。 これは、アンマネージド コードから公開されるリソースにセキュリティ関連 (システム時間、ウィンドウ座標など) がない場合、またはリソースがアセンブリ内でのみ使用され、任意の呼び出し元にパブリックに公開されていない場合です。 このような場合は、関連する API のすべての呼び出し元に対するアンマネージド コード アクセス許可の完全なセキュリティ チェックを抑制できます。 これを行うには、 SuppressUnmanagedCodeSecurity カスタム属性をそれぞれの相互運用メソッドまたはクラスに適用します。 これは、部分的に信頼されたコードがこのような API を悪用できないと判断した場合の、慎重なセキュリティ レビューを前提としています。

[信頼性]

マネージド コードは、アンマネージド コードよりも信頼性と堅牢性が高く設計されています。 これらの品質を促進する CLR 機能の 1 つの例として、メモリ リークを防ぐために未使用のメモリを解放するガベージ コレクションがあります。 もう 1 つの例として、マネージド型の安全性があります。これは、バッファー オーバーランの間違いやその他の型関連のエラーを防ぐために使用されます。

任意の種類の相互運用テクノロジを使用する場合、コードは純粋なマネージド コードほど信頼性が高く、堅牢でない可能性があります。 たとえば、アンマネージド メモリを手動で割り当て、操作が完了したら解放する必要がある場合があります。

単純でない相互運用コードを記述するには、アンマネージド コードの記述と同じ信頼性と堅牢性に注意する必要があります。 すべての相互運用コードが正しく記述されている場合でも、システムはアンマネージド 部分と同じくらい信頼性が高くなります。

パフォーマンス

マネージド コードからアンマネージド コード (およびその逆) に移行するたびに、パフォーマンスのオーバーヘッドが発生します。 オーバーヘッドの量は、使用されるパラメーターの種類によって異なります。 CLR 相互運用レイヤーでは、遷移の種類とパラメーターの種類に基づいて 3 つのレベルの相互運用呼び出しの最適化が使用されます。Just-In-Time (JIT) インライン化、コンパイル済みアセンブリ スタブ、解釈されたマーシャリング スタブ (最も高速から低速の呼び出しの順)。

プラットフォーム呼び出しのおおよそのオーバーヘッド: 10 台のマシン命令 (x86 プロセッサ)

COM 相互運用呼び出しのおおよそのオーバーヘッド: 50 台のマシン命令 (x86 プロセッサ上)

これらの手順で実行される作業については、「フラット API の呼び出し: ステップ バイ ステップ」と「COM API の呼び出し: ステップ バイ ステップ」の付録セクションを参照してください。 呼び出し中にガベージ コレクターがアンマネージ スレッドをブロックしないようにし、呼び出し規約とアンマネージ例外を処理するだけでなく、COM 相互運用機能は、現在のランタイム呼び出し可能ラッパー (RCW) の呼び出しを現在のコンテキストに適した COM インターフェイス ポインターに変換する追加の作業を行います。

すべての相互運用呼び出しでは、いくつかのオーバーヘッドが発生します。 これらの呼び出しが発生する頻度と、メソッド実装内で行われる作業の重要性に応じて、呼び出しごとのオーバーヘッドはごくわずかから非常に顕著なものまで多岐に及ぶ可能性があります。

これらの考慮事項に基づいて、次の一覧に役立つ可能性のある一般的なパフォーマンスの提案をいくつか示します。

  • マネージド コードとアンマネージド コードの間のインターフェイスを制御する場合は、"chatty" ではなく "チャンキー" にして、遷移の合計数を減らします。

    チャット インターフェイスは、相互運用境界の反対側で重要な作業を行うことなく、多くの遷移を行うインターフェイスです。 たとえば、プロパティ セッターとゲッターはチャットです。 分厚いインターフェイスは、いくつかの遷移のみを行うインターフェイスであり、境界の反対側で実行される作業の量は重要です。 たとえば、データベース接続を開き、一部のデータを取得するメソッドはチャンクです。 分厚いインターフェイスでは、相互運用の移行が少なくなっています。そのため、パフォーマンスのオーバーヘッドを排除できます。

  • 可能であれば、Unicode/ANSI 変換は避けてください。

    文字列を Unicode から ANSI に変換し、その逆を行う操作はコストの高い操作です。 たとえば、文字列を渡す必要があるが、その内容が重要でない場合は、文字列パラメーターを IntPtr として宣言できます。相互運用マーシャラーは変換を行いません。

  • 高パフォーマンスのシナリオでは、パラメーターとフィールドを IntPtr として宣言すると、使いやすさと保守性を犠牲にしながらも、パフォーマンスが向上する可能性があります。

    既定の相互運用マーシャリングに依存するのではなく、 Marshal クラスで使用できるメソッドを使用して手動マーシャリングを実行する方が高速な場合があります。 たとえば、相互運用境界を越えて文字列の大きな配列を渡す必要があるが、必要な要素が少ない場合は、配列を IntPtr として宣言し、それらの少数の要素にのみ手動でアクセスする方がはるかに高速になります。

  • InAttributeOutAttribute を賢明に使用して、不要なマーシャリングを減らします。

    相互運用マーシャラーは、呼び出しの前に特定のパラメーターをマーシャリングし、呼び出し後にマーシャリングする必要があるかどうかを決定するときに、既定の規則を使用します。 これらの規則は、間接参照のレベルとパラメーター型に基づいています。 これらの操作の一部は、メソッドのセマンティクスによっては必要ない場合があります。

  • 後で Marshal.GetLastWin32Error を呼び出す場合にのみ、プラットフォーム呼び出しシグネチャで SetLastError=false を使用します。

    プラットフォーム呼び出しシグネチャで SetLastError=true を 設定するには、最後のエラー コードを保持するために相互運用レイヤーからの追加作業が必要です。 この機能は、この情報に依存し、通話後に使用する場合にのみ使用します。

  • アンマネージド呼び出しが悪用不可能な方法で公開されている場合にのみ、 SuppressUnmanagedCodeSecurityAttribute を使用してセキュリティ チェックの数を減らします。

    セキュリティ チェックは非常に重要です。 API で保護されたリソースや機密情報が公開されていない場合、または適切に保護されている場合は、広範なセキュリティ チェックによって不要なオーバーヘッドが発生する可能性があります。 ただし、セキュリティ チェックを行わない場合のコストは非常に高くなります。

付録 1: 相互運用性境界を越える

フラット API の呼び出し: ステップ バイ ステップ

図 3: フラット API の呼び出し

  1. Get LoadLibraryGetProcAddress
  2. ターゲット アドレスを含む署名から DllImport スタブを作成します。
  3. 呼び出し先が保存したレジスタをプッシュします。
  4. DllImport フレームを設定し、フレームのスタックにプッシュします。
  5. 一時メモリが割り当てられている場合は、呼び出しの完了時に迅速に解放するために、クリーンアップ リストを初期化します。
  6. マーシャリング パラメーター。 (これによりメモリが割り当てられる可能性があります)。)
  7. ガベージ コレクション モードを協調モードからプリエンプティブモードに変更して、ガベージ コレクションをいつでも実行できるようにします。
  8. ターゲット アドレスを読み込んで呼び出します。
  9. SetLastError ビットが設定されている場合は、GetLastError を呼び出し、スレッド ローカル ストレージに格納されているスレッド抽象化に結果を格納します。
  10. 協調ガベージ コレクション モードに戻ります。
  11. PreserveSig=false で、メソッドからエラー HRESULT が返された場合は、例外をスローします。
  12. 例外がスローされなかった場合は、back-propagate out パラメーターと by-ref パラメーターです。
  13. 拡張スタック ポインターを元の値に復元して、呼び出し元でポップされた引数を考慮します。

COM API の呼び出し: ステップ バイ ステップ

図 4: COM API の呼び出し

  1. シグネチャからマネージドからアンマネージドスタブを構築します。
  2. 呼び出し先が保存したレジスタをプッシュします。
  3. マネージドからアンマネージドの COM 相互運用機能フレームを設定し、フレームのスタックにプッシュします。
  4. 切り替え中に使用される一時データの領域を予約します。
  5. 一時メモリが割り当てられている場合は、呼び出しの完了時に迅速に解放するために、クリーンアップ リストを初期化します。
  6. 浮動小数点例外フラグをクリアします (x86 のみ)。
  7. マーシャリング パラメーター。 (これによりメモリが割り当てられる可能性があります)。)
  8. ランタイム呼び出し可能ラッパー内の現在のコンテキストの正しいインターフェイス ポインターを取得します。 キャッシュされたポインターを使用できない場合は、COM コンポーネントで QueryInterface を呼び出して取得します。
  9. ガベージ コレクション モードを協調モードからプリエンプティブモードに変更して、ガベージ コレクションをいつでも実行できるようにします。
  10. vtable ポインターからスロット番号でインデックスを付け、ターゲット アドレスを取得して呼び出します。
  11. QueryInterface が以前に呼び出された場合は、インターフェイス ポインターで Release を呼び出します。
  12. 協調ガベージ コレクション モードに戻ります。
  13. 署名が PreserveSig とマークされていない場合は、エラー HRESULT をチェックし、例外をスローします (IErrorInfo 情報が入力されている可能性があります)。
  14. 例外がスローされなかった場合は、back-propagate out パラメーターと by-ref パラメーターです。
  15. 拡張スタック ポインターを元の値に復元して、呼び出し元のポップされた引数を考慮します。

COM からのマネージド API の呼び出し: ステップ バイ ステップ

図 5: COM からのマネージ API の呼び出し

  1. シグネチャからアンマネージドからマネージドスタブを作成します。
  2. 呼び出し先が保存したレジスタをプッシュします。
  3. アンマネージからマネージドへの COM 相互運用フレームを設定し、フレームのスタックにプッシュします。
  4. 切り替え中に使用される一時データの領域を予約します。
  5. ガベージ コレクションをいつでも実行できるように、ガベージ コレクション モードを協調モードからプリエンプティブモードに変更します。
  6. インターフェイス ポインターから COM 呼び出し可能ラッパー (CCW) を取得します。
  7. CCW 内のマネージド オブジェクトを取得します。
  8. 必要に応じて、appdomains を移行します。
  9. appdomain に完全な信頼がない場合は、ターゲット appdomain に対してメソッドが持つ可能性のあるリンク要求を実行します。
  10. 一時メモリが割り当てられている場合は、呼び出しの完了時に迅速に解放するために、クリーンアップ リストを初期化します。
  11. マーシャリング パラメーター。 (これによりメモリが割り当てられる可能性があります)。)
  12. 呼び出すターゲットマネージド メソッドを見つけます。 (これには、ターゲット実装へのインターフェイス呼び出しのマッピングが含まれます)。
  13. 戻り値をキャッシュします。 (浮動小数点の戻り値の場合は、浮動小数点レジスタから取得します)。
  14. 協調ガベージ コレクション モードに戻ります。
  15. 例外がスローされた場合は、返される HRESULT を抽出し、 SetErrorInfo を呼び出します。
  16. 例外がスローされなかった場合は、back-propagate out パラメーターと by-ref パラメーターです。
  17. 拡張スタック ポインターを元の値に復元して、呼び出し元のポップされた引数を考慮します。

付録 2: リソース

読む必要があります。.NET と COM: Adam Nathan による完全な相互運用性ガイド

アンマネージド コードとの相互運用、Microsoft .NET Framework 開発者ガイド

相互運用のサンプル、Microsoft .NET Framework

Adam Nathan の ブログ

Chris Brumme の ブログ

付録 3: 用語集

AppDomain (アプリケーション ドメイン) アプリケーション ドメインは軽量 OS プロセスに似ていると見なすことができ、共通言語ランタイムによって管理されます。
CCW (COM 呼び出し可能ラッパー) COM コードからアクティブ化されたマネージド オブジェクトの周囲に CLR 相互運用レイヤーによって作成される特別な種類のラッパー。 CCW は、データ マーシャリング、有効期間管理、ID 管理、エラー処理、適切なアパートメントとスレッドの遷移などを提供することで、マネージド オブジェクト モデルと COM オブジェクト モデルの違いを非表示にします。 CCW は、マネージド コード実装者が COM プラミングについて何も知らなくても、COM フレンドリな方法でマネージド オブジェクト機能を公開します。
CLR 共通言語ランタイム。
COM 相互運用 マネージド コードから COM API を使用したり、マネージド API を COM API としてアンマネージ クライアントに公開したりするために、CLR 相互運用レイヤーによって提供されるサービス。 COM 相互運用機能は、すべてのマネージド言語で使用できます。
C++ 相互運用機能 C++ 言語コンパイラと CLR によって提供されるサービスは、同じ実行可能ファイル内のマネージド コードとアンマネージド コードを直接混在するために使用されます。 C++ 相互運用には、通常、アンマネージ API にヘッダー ファイルを含め、特定のコーディング規則に従う必要があります。
複雑なフラット API マネージド言語で宣言するのが難しい署名を持つ API。 たとえば、可変サイズの構造体パラメーターを持つメソッドは、マネージド型システムに同等の概念がないため、宣言が困難です。
Interop マネージド コードとアンマネージド コード ("ネイティブ" とも呼ばれます) の間の任意の種類の相互運用性をカバーする一般的な用語。 相互運用機能は、CLR によって提供される多くのサービスの 1 つです。
相互運用機能アセンブリ タイプ ライブラリに含まれる COM 型に相当するマネージド型を含む特殊な型のマネージド アセンブリ。 通常、タイプ ライブラリ インポーター ツール (Tlbimp.exe) をタイプ ライブラリで実行することによって生成されます。
マネージド コード CLR の制御下で実行されるコードは、マネージド コードと呼ばれます。 たとえば、C# または Visual Basic .NET で記述されたコードはマネージド コードです。
プラットフォーム呼び出し マネージド コードからアンマネージド フラット API を呼び出すための CLR 相互運用レイヤーによって提供されるサービス。 プラットフォーム呼び出しは、すべてのマネージド言語で使用できます。
RCW (ランタイム呼び出し可能な wapper) マネージド コードからアクティブ化される COM オブジェクトの周囲に CLR 相互運用レイヤーによって作成される特別な種類のラッパー。 RCW は、データ マーシャリング、有効期間管理、ID 管理、エラー処理、適切なアパートメントとスレッドの遷移などを提供することで、マネージド オブジェクト モデルと COM オブジェクト モデルの違いを隠します。
アンマネージド コード CLR の外部で実行されるコードは、"アンマネージ コード" と呼ばれます。COM コンポーネント、ActiveX コンポーネント、および Win32 API 関数は、アンマネージド コードの例です。