注
Microsoft Foundation Classes (MFC) ライブラリは引き続きサポートされています。 ただし、機能の追加やドキュメントの更新は行われません。
このノートでは、通常の MFC DLL について説明します。MFC ライブラリを Windows ダイナミック リンク ライブラリ (DLL) の一部として使用できます。 Windows DLL とその構築方法を理解していることを前提としています。 MFC ライブラリの拡張機能を作成できる MFC 拡張 DLL の詳細については、「 MFC の DLL バージョン」を参照してください。
DLL インターフェイス
通常の MFC DLL は、アプリケーションと DLL の間のインターフェイスが C のような関数または明示的にエクスポートされたクラスで指定されていることを前提としています。 MFC クラス インターフェイスはエクスポートできません。
DLL とアプリケーションの両方で MFC を使用する場合は、MFC ライブラリの共有バージョンを使用するか、ライブラリのコピーに静的にリンクするかを選択できます。 アプリケーションと DLL の両方で、MFC ライブラリの標準バージョンのいずれかを使用できます。
通常の MFC DLL には、いくつかの利点があります。
DLL を使用するアプリケーションは、MFC を使用する必要はありません。また、Visual Studio アプリケーションである必要はありません。
MFC に静的にリンクする通常の MFC DLL では、DLL のサイズは、使用およびリンクされている MFC および C ランタイム ルーチンにのみ依存します。
MFC に動的にリンクする通常の MFC DLL では、MFC の共有バージョンを使用するメモリの節約が重要になる可能性があります。 ただし、共有 DLL である Mfc<version>.dll および Msvvcrt<version>.dllを DLL と共に配布する必要があります。
DLL の設計は、クラスの実装方法とは無関係です。 DLL デザインは、必要な API にのみエクスポートします。 その結果、実装が変更された場合でも、通常の MFC DLL は引き続き有効です。
MFC に静的にリンクする通常の MFC DLL では、DLL とアプリケーションの両方で MFC を使用する場合、DLL とは異なるバージョンの MFC を必要とするアプリケーションに問題はありません。その逆も同様です。 MFC ライブラリは各 DLL または EXE に静的にリンクされているため、使用しているバージョンに関する質問はありません。
API の制限事項
MFC の一部の機能は、技術的な制限のため、またはこれらのサービスが通常アプリケーションによって提供されるため、DLL バージョンには適用されません。 MFC の現在のバージョンでは、適用できない唯一の関数は CWinApp::SetDialogBkColor。
DLL のビルド
MFC に静的にリンクする通常の MFC DLL をコンパイルする場合は、シンボル _USRDLL と _WINDLL を定義する必要があります。 DLL コードは、次のコンパイラ スイッチを使用してコンパイルする必要もあります。
/D_WINDLL は、コンパイルが DLL 用であることを示します
/D_USRDLL は、通常の MFC DLL をビルドしていることを指定します
また、MFC に動的にリンクする通常の MFC DLL をコンパイルするときに、これらのシンボルを定義し、これらのコンパイラ スイッチを使用する必要があります。 さらに、シンボル _AFXDLL を定義し、DLL コードを次のようにコンパイルする必要があります。
- /D_AFXDLL は、MFC に動的にリンクする通常の MFC DLL を構築することを指定します。
アプリケーションと DLL の間のインターフェイス (API) を明示的にエクスポートする必要があります。 インターフェイスを低帯域幅に定義し、可能な場合は C インターフェイスのみを使用することをお勧めします。 直接 C インターフェイスは、より複雑な C++ クラスよりも保守が容易です。
C ファイルと C++ ファイルの両方に含めることができる個別のヘッダーに API を配置します。 例については、MFC Advanced Concepts サンプル DLLScreenCap のヘッダー ScreenCap.h を参照してください。 関数をエクスポートするには、モジュール定義ファイルの EXPORTS セクションに関数を入力します (.DEF) を使用するか、関数定義に __declspec(dllexport) を含めます。
__declspec(dllimport)を使用して、これらの関数をクライアント実行可能ファイルにインポートします。
MFC に動的にリンクする標準 MFC DLL 内のすべてのエクスポートされた関数の先頭に、AFX_MANAGE_STATE マクロを追加する必要があります。 このマクロは、現在のモジュールの状態を DLL の状態に設定します。 このマクロを使用するには、DLL からエクスポートされた関数の先頭に次のコード行を追加します。
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
WinMain -> DllMain
MFC ライブラリは、標準的な MFC アプリケーションと同様に DllMain 派生オブジェクトを初期化する標準的な Win32 エントリ ポイントを定義します。 一般的な MFC アプリケーションと同様に、すべての DLL 固有の初期化を InitInstance メソッドに配置します。
アプリケーションがメイン メッセージ ポンプを所有しているため、 CWinApp::Run メカニズムは DLL には適用されないことに注意してください。 DLL がモードレス ダイアログを表示する場合や独自のメイン フレーム ウィンドウを持つ場合、アプリケーションのメイン メッセージ ポンプは CWinApp::PreTranslateMessage を呼び出す DLL エクスポート ルーチンを呼び出す必要があります。
この関数の使用については、DLLScreenCap サンプルを参照してください。
MFC が提供するDllMain関数は、DLL がアンロードされる前に、から派生したクラスの CWinApp メソッドを呼び出します。
あなたのDLLをリンクする
MFC に静的にリンクする通常の MFC DLL では、DLL を Nafxcwd.lib または Nafxcw.lib にリンクし、Libcmt.lib という名前の C ランタイムのバージョンとリンクする必要があります。 これらのライブラリは事前に構築されており、Visual Studio セットアップの実行時に指定してインストールできます。
サンプル コード
完全なサンプルについては、MFC Advanced Concepts サンプル プログラム DLLScreenCap を参照してください。 このサンプルでは、次のような興味深い点に注意してください。
DLL のコンパイラ フラグとアプリケーションのコンパイラ フラグは異なります。
リンク行と .DLL 用の DEF ファイルとアプリケーション用のファイルは異なります。
DLL を使用するアプリケーションが C++ である必要はありません。
アプリケーションと DLL の間のインターフェイスは、C または C++ で使用できる API であり、DLLScreenCap.def を使用してエクスポートされます。
次の例は、MFC に静的にリンクする通常の MFC DLL で定義されている API を示しています。 この例では、宣言は C++ ユーザーの extern "C" { } ブロックで囲まれています。 これにはいくつかの利点があります。 まず、C++ 以外のクライアント アプリケーションで DLL API を使用できるようにします。 次に、C++ 名のマングリングがエクスポートされた名前に適用されないため、DLL のオーバーヘッドが軽減されます。 最後に、名前修飾を気にすることなく、.DEF ファイルへの明示的な追加 (序数でエクスポートするため) が容易になります。
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct TracerData
{
BOOL bEnabled;
UINT flags;
};
BOOL PromptTraceFlags(TracerData FAR* lpData);
#ifdef __cplusplus
}
#endif
API によって使用される構造体は MFC クラスから派生せず、API ヘッダーで定義されます。 これにより、DLL とアプリケーション間のインターフェイスの複雑さが軽減され、C プログラムで DLL を使用できるようになります。