方法: /clr:pure に移行する (C++/CLI)
このトピックでは、/clr:pure を使用して純粋 MSIL に移行するときに発生する可能性のある問題について説明します (詳細については、「/clr (共通言語ランタイムのコンパイル)」 を参照してください)。 このトピックでは、アンマネージ コードから純粋 MSIL への移行パスが直接的なパスでないため、移行するコードが、/clr オプションを使用して混在アセンブリとして現在コンパイルされていることを想定しています。 アンマネージ コードを純粋 MSIL に移行する場合は、事前に「方法: /clr に移行する」を参照してください。
基本的な変更点
純粋 MSIL は、MSIL 命令で構成されているので、MSIL で表現できない関数を含んでいるコードはコンパイルしません。 こうした関数には、__clrcall 以外の呼び出し規約を使用するように定義されている関数が該当します (__clrcall 以外の関数について、純粋 MSIL コンポーネントで呼び出すことはできますが、定義することはできません)。
実行時エラーが発生しないようにするには、C4412 警告を有効にする必要があります。 C4412 を有効にするには、/clr:pure を使用してコンパイルし、C++ 型を IJW (/clr) またはネイティブ コードに、またはその逆の受け渡しをする各コンパイル単位に #pragma warning (default : 4412) を追加します。 詳細については、「コンパイラの警告 (レベル 2) C4412」を参照してください。
アーキテクチャに関する考慮事項
純粋なコードと検証可能なコード (C++/CLI) に一覧されている純粋 MSIL アセンブリの制限の中に、アプリケーション デザインと移行計画について重要な意味を持つものがあります。 最も重要なことは、純粋 MSIL アセンブリは、混在アセンブリとは異なり、アンマネージ モジュールとの完全な互換性がないことです。
純粋 MSIL アセンブリは、アンマネージ関数を呼び出すことができますが、アンマネージ関数からこのアセンブリを呼び出すことはできません。 したがって、純粋 MSIL は、アンマネージ関数によって使用されるサーバー コードよりも、アンマネージ関数を使用するクライアント コードに適しています。 純粋 MSIL アセンブリに含まれる機能がアンマネージ関数によって使用される場合、混在アセンブリをインターフェイス層として使用する必要があります。
今回のリリースでは ATL ライブラリおよび MFC ライブラリがサポートされていないので、ATL または MFC を使用するアプリケーションは、純粋 MSIL への移行には適していません。 同様に、Windows SDK には、/clr:pure ではコンパイルされないヘッダー ファイルが含まれています。
純粋 MSIL アセンブリからアンマネージ関数を呼び出すことはできますが、これができるのは、単純な C スタイルの関数に限られます。 より複雑なアンマネージ API を使用するには、COM インターフェイス形式、つまり、純粋 MSIL とアンマネージ コンポーネント間のインターフェイスとして機能する混在アセンブリ形式で、アンマネージ機能を公開する必要があります。 たとえば、純粋アセンブリがコールバックとして使用するためにネイティブな呼び出し可能関数を提供できない場合に、コールバック関数を受け取るアンマネージ関数を使用する唯一の方法は、混在アセンブリを使用することです。
アプリケーション ドメインと呼び出し規約
純粋 MSIL アセンブリはアンマネージ機能を使用できますが、関数と静的データは別々に処理されます。 純粋アセンブリでは、関数は __clrcall 呼び出し規約を使用して実装され、静的データはアプリケーション ドメイン単位で格納されます。 これは、アンマネージおよび混在アセンブリの既定とは異なります。アンマネージ アセンブリおよび混在アセンブリでは、関数に対して __cdecl 呼び出し規約が使用され、静的データはプロセス ベースで格納されます。
純粋 MSIL (および /clr:safe でコンパイルされる検証可能なコード) のコンテキストでは、__clrcall が CLR の既定の呼び出し規約になり、アプリケーション ドメインが、.NET アプリケーション内の静的データおよびグローバル データのネイティブ スコープであるため、これらの既定をユーザーが意識することはありません。 ただし、アンマネージ コンポーネントまたは混合コンポーネントとの間でインターフェイスをとるときには、関数およびグローバル データの処理の違いが、問題の原因になる場合があります。
たとえば、純粋 MSIL コンポーネントがアンマネージ DLL または混合 DLL 内の関数を呼び出す場合、純粋アセンブリをコンパイルするために DLL のヘッダー ファイルが使用されます。 ただし、ヘッダー内の各関数の呼び出し規約が明示的に示されていない限り、これらの呼び出し規約はすべて __clrcall と見なされます。 これが、後で実行時エラー発生の原因になることがあります。これらの関数が __cdecl 規約によって実装されるからです。 アンマネージ ヘッダー ファイルの関数には、__cdecl として明示的にマークを付けることができます。これを行わない場合は、DLL ソース コード全体を /clr:pure を使用して再コンパイルする必要があります。
同様に、関数ポインターは、/clr:pure コンパイルによって __clrcall 関数をポイントする必要があります。 これら 2 つの事項は、適切な呼び出し規約に明示的に記載される必要があります。
詳細については、「アプリケーション ドメインと Visual C++」を参照してください。
リンクに関する制限事項
Visual C++ リンカーは、ストレージ スコープと呼び出し規約が異なるため、混合および純粋の OBJ ファイルをリンクしません。