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

 

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、Internet Explorer、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 として公開できる唯一の高度な言語です。 これを行うことは、マネージ API を COM 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 プロセッサ上)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. LoadLibraryGetProcAddress を取得します
  2. ターゲット アドレスを含む署名から DllImport スタブをビルドします。
  3. 呼び出し先で保存されたレジスタをプッシュします。
  4. DllImport フレームを設定し、フレームのスタックにプッシュします。
  5. 一時メモリが割り当てられている場合は、呼び出しが完了したときに迅速に解放されるようにクリーンアップ リストを初期化します。
  6. マーシャリング パラメーター。 (これによりメモリが割り当てられる可能性があります)。)
  7. ガベージ コレクション モードを連携モードからプリエンプティブモードに変更して、ガベージ コレクションをいつでも実行できるようにします。
  8. ターゲット アドレスを読み込んで呼び出します。
  9. SetLastError ビットが設定されている場合は、GetLastError を呼び出し、その結果をスレッド ローカル Storageに格納されたスレッド抽象化に格納します。
  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. 例外がスローされなかった場合は、バックプロパ ゲート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# または .NET Visual Basicで記述されたコードはマネージド コードです。
プラットフォーム呼び出し マネージド コードからアンマネージ フラット API を呼び出すための CLR 相互運用レイヤーによって提供されるサービス。 プラットフォーム呼び出しは、すべてのマネージド言語で使用できます。
RCW (ランタイム呼び出し可能な wapper) マネージド コードからアクティブ化される COM オブジェクトに関する CLR 相互運用レイヤーによって作成される特別な種類のラッパー。 RCW は、データ マーシャリング、有効期間管理、ID 管理、エラー処理、正しいアパートメントとスレッドの遷移などを提供することで、マネージド オブジェクト モデルと COM オブジェクト モデルの違いを隠します。
アンマネージド コード CLR の外部で実行されるコードは、"アンマネージ コード" と呼ばれます。COM コンポーネント、ActiveX コンポーネント、および Win32 API 関数は、アンマネージ コードの例です。