次の方法で共有


テクニカル ノート 33: MFC の DLL バージョン

ここでは、 MFC のアプリケーションおよび拡張ダイナミック リンク ライブラリの MFCxx.DLL と MFCxxD.DLL (x は MFC のバージョン番号)共有ダイナミック リンク ライブラリを使用する方法について説明します。レギュラー DLL に関する詳細については、 DLL の一部として MFC を使用するを参照してください。

このテクニカル ノートは、 DLL の 3 種類の辺について説明します。最後の 2 つが詳細に上級ユーザー向けです:

  • MFC 拡張 DLL をビルドまたは

  • MFC DLL バージョンを使用する MFC アプリケーションをビルドまたは

  • MFC 共有ダイナミック リンク ライブラリを実行する方法

ビルドする必要がある場合は非 MFC アプリケーション (このレギュラー DLL で使用できる呼ばれます)と MFC を使用して DLL が テクニカル ノート 11を参照してください。

MFCxx.DLL サポートの概要: 用語とファイル

Regular DLL: MFC クラスのいくつかを使用して、スタンドアロン DLL をビルドとレギュラー DLL を使用します。App/DLL の境界を越えてインターフェイスは 「15 C」インターフェイスであり、クライアント アプリケーションは、 MFC アプリケーションである必要はありません。

これは、 MFC 1.0 でサポートされる DLL サポートのバージョンです。これは テクニカル ノート 11 に記述され、 MFC の高度な概念は DLLScreenCapをサンプリングします。

[!メモ]

Visual C++ バージョン 4.0 の時点で、用語 USRDLL は、 MFC にされるレギュラー DLL では廃止され、静的にリンクされる置き換えられました。また、 MFC と動的にリンクするされるレギュラー DLL をビルドできます。

MFC 3.0 (以上)に OLE、およびデータベース クラスを含むすべての新機能の標準 DLL をサポートします。

AFXDLL: これは、 MFC ライブラリの共有バージョンと呼ばれます。これは、 MFC 2.0 で追加された新しい DLL サポートです。MFC ライブラリ自体は複数の DLL にあり、 (以下で説明)クライアント アプリケーションと DLL に動的に必要な DLL をリンクします。application/DLL の境界を越えてインターフェイスは C++/MFC のクラス インターフェイスです。クライアント アプリケーションは、 MFC アプリケーションである必要があります。これは、すべての MFC 3.0 の機能 (例外をサポートします: UNICODE は、データベース クラスではサポートされません)。

[!メモ]

Visual C++ バージョン 4.0 の時点で、この種の DLL は 「拡張 DLL と呼ばれます」。

ここでは、次のような全体の MFC DLL セットを示すために MFCxx.DLL を使用して:

  • デバッグ: MFCxxD.DLL (合わせて)と MFCSxxD.LIB (静的)。

  • リリース: MFCxx.DLL (合わせて)と MFCSxx.LIB (静的)。

  • Unicode デバッグ: MFCxxUD.DLL (合わせて)と MFCSxxD.LIB (静的)。

  • Unicode リリース: MFCxxU.DLL (合わせて)と MFCSxxU.LIB (静的)。

[!メモ]

MFCSxx [U] [17 C] .LIB ライブラリは、 MFC の共有 DLL とともに使用されます。これらのライブラリは、アプリケーションまたは DLL に静的にリンクするコードが含まれています。

対応するインポート ライブラリにリンクするアプリケーションの場合:

  • デバッグ: MFCxxD.LIB

  • リリース: MFCxx.LIB

  • Unicode デバッグ: MFCxxUD.LIB

  • Unicode リリース: MFCxxU.LIB

「MFC 拡張 DLL は」、 MFCxx.DLL です (それ以外の MFC 共有 DLL)にビルドされた DLL。ここでは、 MFC コンポーネントのアーキテクチャはアクティブになります。MFC クラスから便利なクラスを取得または別の MFC のようなツールキットをビルド、 DLL に配置することもできます。DLL は MFCxx.DLL は、使用すると、最終的なクライアント アプリケーション。この割り当ての再利用可能なリーフのクラス、再利用可能な基本クラスと再利用可能なビューまたはドキュメント クラス。

使う場合

理由 MFC の共有バージョンを使用する必要があるか。

  • 共有ライブラリを使用するよりも小さなアプリケーション (最小アプリケーションの MFC ライブラリの値より小さいサイズの最も使用)が発生することがあります。

  • MFC の共有バージョンは、 MFC 拡張ダイナミック リンク ライブラリとレギュラー DLL をサポートします。

  • MFC 共有ライブラリを使用するアプリケーションをビルド MFC 自体をリンクする必要がないため、静的にリンクされる MFC アプリケーションをビルドより高速です。これは、リンカーがデバッグ情報を圧縮する必要がある 追加 のビルドに指示できます (デバッグ情報を既に含む DLL とリンクして…アプリケーション内に圧縮されるデバッグ情報が少なくなります。

MFC の共有バージョンを使用する必要がある場合:

  • 共有ライブラリを使用するアプリケーションを出荷すると、プログラムで MFCxx.DLL (など)ライブラリを用意する必要があります。MFCxx.DLL は多くの DLL と同じように自由に再頒布可能ですが、セットアップ プログラムで DLL をインストールします。また、プログラムと MFC DLL 自体の両方で使用される 15 C のランタイム ライブラリを含む MSVCRTxx.DLL を提供します。

MFC 拡張 DLL を作成する方法

MFC の拡張 DLL は、 MFC クラスの機能を拡張するために記述された DLL のコンテナー クラス、および関数です。MFC の拡張 DLL は共有 MFC DLL をアプリケーションで使用すると、追加情報を使用して、同じように使用します:

  • ビルド処理には数個 MFC 共有ライブラリを追加すると、コンパイラとリンカー オプションを使用するアプリケーションをビルドに似ています。

  • MFC 拡張 DLL に CWinApp派生クラスはありません。

  • MFC の拡張 DLL は、特殊な DllMainを提供する必要があります。AppWizard は、変更できる DllMain 関数を提供します。

  • MFC の拡張 DLL は、通常、拡張 DLL がアプリケーションに CRuntimeClasses またはリソースをエクスポートする場合 CDynLinkLibrary を作成するために初期化ルーチンがあります。CDynLinkLibrary の派生クラスは、アプリケーション データが拡張 DLL によって保持する必要がある場合に使用されることがあります。

これらの考慮事項は後で詳しく説明します。示すように、 MFC の高度な概念のサンプル DLLHUSK を参照する必要があります:

  • 共有ライブラリを使用してアプリケーションをビルドします。(DLLHUSK.EXE は、 MFC ライブラリ、またはそのほかの DLL と動的にリンクする MFC アプリケーションであり)

  • MFC 拡張 DLL をビルドします。(拡張 DLL をビルドに使用される _AFXEXT のような特殊なフラグに注意してください)。

  • MFC 拡張ダイナミック リンク ライブラリの 2 例。1 つが、限られたエクスポート (TESTDLL1)およびそのほかの MFC 拡張 DLL の基本的な構造全体をクラス インターフェイス (TESTDLL2)をエクスポートするに示します。

クライアント アプリケーションおよび拡張ダイナミック リンク ライブラリはどちら MFCxx.DLL の同じバージョンを使用する必要があります。MFC DLL の規則に従って、デバッグを提供し、 (拡張 DLL の /release)バージョンをリリースする必要があります。アプリケーションのデバッグ バージョンとリテール バージョンの両方をビルド、すべての DLL の適切なデバッグまたはリテール バージョンとリンクするこの割り当てのクライアント プログラム。

[!メモ]

C++ の名前の利点になるとエクスポートの問題が、拡張 DLL からエクスポート リスト異なるプラットフォームで同じ DLL と DLL のデバッグ バージョンとリテール バージョンごとに異なる場合があるためです。リテール MFCxx.DLL には、約 2000 のエクスポート エントリ ポイントがあります。; デバッグ MFCxxD.DLL には、約 3000 のエクスポート エントリ ポイントがあります。

hw85e4bb.collapse_all(ja-jp,VS.110).gifメモリ管理の高速メモ

このテクニカル ノートの末尾付近のメモリ管理、 「」というセクションでは、 MFC の共有バージョンとの MFCxx.DLL の実装について説明します。、拡張 DLL を実行するために、知る必要がある情報はここで記述されます。

同じアプリケーションに存在するようにクライアント アプリケーションのアドレス空間に読み込まれた MFCxx.DLL とすべての拡張ダイナミック リンク ライブラリを同じメモリ アロケーター、リソースの読み込みおよびそのほかの MFC の 「Global」状態を使用します。これは、 MFC と静的にリンクするレギュラー DLL と非 MFC DLL のライブラリが厳密をのオブジェクトのし、独自のメモリ プールから割り当てた各 DLL があるためです。

拡張 DLL に割り当てられたメモリは他のアプリケーション割り当てられたオブジェクトも自由に使用できます。また、 MFC 共有ライブラリを使用するアプリケーションがクラッシュすると、オペレーティング システムの保護は、他の MFC アプリケーションの一貫性が共有 DLL 保持します。

同様に、リソースをで、クライアント アプリケーションとすべての MFC 拡張ダイナミック リンク ライブラリ、または MFCxx.DLL 自体の間で読み込む現在の実行可能ファイルなど、他の 「」グローバルな MFC の状態は、共有されます。

hw85e4bb.collapse_all(ja-jp,VS.110).gif拡張 DLL をビルド

MFC 拡張 DLL プロジェクトを作成するには、 AppWizard を使用して自動的に適切なコンパイラとリンカーの設定を生成します。また、生成して、変更できる DllMain の関数を発生しました。

MFC 拡張 DLL は、既存のプロジェクトを変換している場合は、アプリケーションをビルドするための標準規則から MFC の共有バージョンを使用して開始、次を実行します:

  • コンパイラ フラグに /D_AFXEXT を追加します。プロジェクトのプロパティ] ダイアログで、 C/C++ ノードを選択します。次に、プリプロセッサのカテゴリを選択します。定義のマクロに _AFXEXT をフィールドに対して、追加し、セミコロンの項目のそれぞれが分離されます。

  • /Gy のコンパイラ スイッチを削除します。プロジェクトのプロパティ] ダイアログで、 C/C++ ノードを選択します。このコードのジェネレーション カテゴリを選択します。オプションを 「リンクする」有効関数レベルが有効でないことを確認します。これは、リンカーが参照されていない関数を削除しないためクラスをエクスポートしやすくなります。MFC と静的にリンクされるレギュラー DLL をビルド元のプロジェクトが使用された場合 **/MD[d]**に /MT[d] のコンパイラ オプションを変更します。

  • リンクするに /DLL オプションのエクスポートのライブラリをビルドします。これは、新しいターゲットを作成するときに設定され、 Win32 ダイナミック リンク ライブラリをターゲット型として指定します。

hw85e4bb.collapse_all(ja-jp,VS.110).gifヘッダー ファイルの変更

拡張 DLL の目的は、通常、その機能を使用して一つ以上のアプリケーションに共通の機能をエクスポートします。これは、クライアント アプリケーションで使用できるグローバル関数、およびクラスのエクスポートに沸きます。

これを行うには、メンバー関数のそれぞれが適切にインポートまたはエクスポートとしてマークされることを保証します。これは、特別な宣言が必要です: __declspec(dllexport)__declspec(dllimport)。クラスは、クライアント アプリケーションで使用される場合、その関数に **__declspec(dllimport)**として宣言します。拡張 DLL 自体がビルドされている場合は、 **__declspec(dllexport)**として宣言する必要があります。また、関数は、クライアント プログラムが読み取り時にバインドするように実際にエクスポートする必要があります。

クラス全体をエクスポートするには、クラス定義で AFX_EXT_CLASS を使用します。このマクロは __declspec(dllexport) と、フレームワークによって _AFXEXT を定義しない場合 _AFXDLL_AFXEXT が定義されますが定義されていますが、 __declspec(dllimport) で定義されたとき。既に 説明したように**_AFXEXT** は、拡張 DLL をビルド場合にのみ定義されます。次に例を示します。

class AFX_EXT_CLASS CExampleExport : public CObject
{ ... class definition ... };

hw85e4bb.collapse_all(ja-jp,VS.110).gifクラス全体をエクスポートしない場合

クラスの、個々の必要なメンバーをエクスポートする場合があります。たとえば、CDialog 派生クラスをエクスポートする場合、エクスポートする必要があるのはコンストラクターと DoModal 呼び出しだけです。DLL の .DEF ファイルを使用してこれらのメンバーをエクスポートできますが、エクスポートする必要がある二つのメンバーの AFX_EXT_CLASS をほとんど同じ方法で使用できます。

次に例を示します。

class CExampleDialog : public CDialog
{
public:
   AFX_EXT_CLASS CExampleDialog();
   AFX_EXT_CLASS int DoModal();
   // rest of class definition
   .
   .
   .
};

これを行うと、そのクラスのすべてのメンバーをエクスポートしていないため、別の問題に実行できます。問題は、 MFC のマクロの動作方法であります。MFC のいくつかのヘルパー マクロは、実際にデータ メンバーを宣言または定義しています。したがって、これらのデータ メンバーは、 DLL からエクスポートされる必要があります。

たとえば、拡張 DLL をビルドする場合、DECLARE_DYNAMIC マクロは次のように定義されます。

#define DECLARE_DYNAMIC(class_name) \
protected: \
   static CRuntimeClass* PASCAL _GetBaseClass(); \
   public: \
   static AFX_DATA CRuntimeClass class##class_name; \
   virtual CRuntimeClass* GetRuntimeClass() const; \

「静的 AFX_DATA」を開始する行は、クラス内部の静的オブジェクトを宣言しています。このクラスを正しくエクスポートし、クライアントから .EXE ランタイム情報にアクセスするには、この静的オブジェクトをエクスポートする必要があります。この静的オブジェクトは修飾子 AFX_DATA を付けて宣言されているため、DLL をビルドする場合は AFX_DATA__declspec(dllexport) として定義し、クライアント実行可能ファイルをビルドする場合は __declspec(dllimport) として定義するだけで済みます。

上で説明したように、 AFX_EXT_CLASS は、既にこのように定義されます。クラス定義の周囲に AFX_EXT_CLASS と同じように AFX_DATA を定義し直す必要があります。

次に例を示します。

   #undef  AFX_DATA
   #define AFX_DATA AFX_EXT_CLASS
   class CExampleView : public CView
   {
     DECLARE_DYNAMIC()
     // ... class definition ...
   };
   #undef  AFX_DATA
   #define AFX_DATA

MFC は、マクロ内で定義するため、この手法は、このようなすべてのシナリオに適用データ項目の AFX_DATA のシンボルを常に使用します。たとえば、 DECLARE_MESSAGE_MAPに適用されます。

[!メモ]

選択したクラス メンバーではなく、クラス全体をエクスポートする場合、静的データ メンバーは自動的にエクスポートされます。

自動的に DECLARE_SERIALIMPLEMENT_SERIAL マクロを使用するクラスの CArchive の複数の入力をエクスポートする同じ手法を使用できます。クラス宣言のエクスポートします (にあるブラケットでアーカイブの演算子が。次のコードの H ファイル):

#undef AFX_API
#define AFX_API AFX_EXT_CLASS

<your class declarations here>

#undef AFX_API
#define AFX_API

hw85e4bb.collapse_all(ja-jp,VS.110).gif_AFXEXT に関する制限事項

拡張ダイナミック リンク ライブラリの複数のレイヤーがない限り拡張ダイナミック リンク ライブラリに _のAFXEXT のプリプロセッサ シンボルを使用できます。MFC クラスから派生している独自の拡張 DLL の中のクラスを呼び出したり、このようなクラスから派生している拡張 DLL がある場合は、あいまいさを避けるために必ず独自のプリプロセッサ シンボルを使ってください。

Win32 での問題は、DLL からエクスポートされるデータは __declspec(dllexport) として、DLL からインポートされるデータは __declspec(dllimport) として、それぞれすべて明示的に宣言する必要があることです。_AFXEXT を定義すると、MFC ヘッダーは AFX_EXT_CLASS が正しく定義されているかどうか確認します。

複数のレイヤーがある場合、 AFX_EXT_CLASS のような 1 種類のシンボルは、拡張 DLL が新しいクラスをエクスポートする、または別の拡張 DLL から他のクラスをインポートすることがあるため、十分ではありません。この問題に対処するためには、 DLL の使用と DLL 自体をビルドことを示す特別なプリプロセッサ シンボルを使用します。たとえば、 2 拡張ダイナミック リンク ライブラリ、 A.DLL、および B.DLL とします。それぞれがエクスポート A.H と B.H のあるクラス、それぞれ。B.DLL は A.DLL のクラスを使用します。このとき、ヘッダー ファイルは次のようになります。

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A   __declspec(dllexport)
#else
   #define CLASS_DECL_A   __declspec(dllimport)
#endif

class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };

/* B.H */
#ifdef B_IMPL
   #define CLASS_DECL_B   __declspec(dllexport)
#else
   #define CLASS_DECL_B   __declspec(dllimport)
#endif

class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition .. };

A.DLL のビルド時に、 /D A_IMPL でビルドされ、 B.DLL のビルド時に、 /D B_IMPLでビルドされます。それぞれの DLL でシンボルを使用して、 CExampleB はエクスポートされ、 B.DLL をビルドと CExampleA がインポートされます。CExampleA は B.DLL A.DLL をビルドとエクスポートおよびインポートされます (または他のクライアント)によって使用された場合。

レイヤー表示のこの型は _AFXEXT の組み込みの AFX_EXT_CLASS とプリプロセッサ シンボルを使用するときにすることはできません。前に説明した手法は機能の MFC 自体の使用とは異なり、 OLE データベースとネットワーク拡張ダイナミック リンク ライブラリをビルド、この問題がない方法で解決します。

hw85e4bb.collapse_all(ja-jp,VS.110).gifクラス全体をエクスポートしない場合

再度クラス全体をエクスポートしない場合、特別な対策があります。MFC のマクロによって作成される必要なデータ項目が正しくエクスポートされることを確認する必要があります。これは、特定のクラスのマクロに AFX_DATA を再定義することによって行うことができます。クラス全体をエクスポートしない場合は、必ずこの処理を行う必要があります。

次に例を示します。

// A.H
#ifdef A_IMPL
   #define CLASS_DECL_A  _declspec(dllexport)
#else
   #define CLASS_DECL_A  _declspec(dllimport)
   #endif

#undef  AFX_DATA
#define AFX_DATA CLASS_DECL_A

class CExampleA : public CObject
{
   DECLARE_DYNAMIC()
   CLASS_DECL_A int SomeFunction();
   //class definition 
   .
   .
   .
};

#undef AFX_DATA
#define AFX_DATA

hw85e4bb.collapse_all(ja-jp,VS.110).gifDllMain

ここでは、拡張 DLL 用のメイン ソース ファイルに配置する厳密コードです。この機能は、標準に含まれている後に記述する必要があります。拡張 DLL の開始ファイルを作成するには、 AppWizard を使用する場合に、指定できます。たとえば、の DllMain を確認します。

#include "afxdllx.h"

static AFX_EXTENSION_MODULE extensionDLL;

extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
   if (dwReason == DLL_PROCESS_ATTACH)
   {
      // Extension DLL one-time initialization 
      if (!AfxInitExtensionModule(
             extensionDLL, hInstance))
         return 0;

      // TODO: perform other initialization tasks here
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
      // Extension DLL per-process termination
      AfxTermExtensionModule(extensionDLL);

          // TODO: perform other cleanup tasks here
   }
   return 1;   // ok
}

AfxInitExtensionModule への呼び出しは CDynLinkLibrary のオブジェクトが作成されるとモジュールのランタイム クラス (CRuntimeClass の構造体)、後で使用するためのオブジェクト ファクトリ (COleObjectFactory のオブジェクト)をキャプチャします。AfxTermExtensionModule への (省略可能)呼び出しはクリーンアップ (プロセス終了するとき、または DLL が FreeLibrary の呼び出しの結果として)アンロードされる各プロセスをデタッチするときに MFC 拡張 DLL から拡張 DLL を示します。ほとんどの拡張ダイナミック リンク ライブラリを動的に (通常、インポート ライブラリとリンクされます)読み込まれていないため、 AfxTermExtensionModule への呼び出しは、通常は必要ではありません。

アプリケーションが拡張ダイナミック リンク ライブラリを動的に読み取り、放したら、上記のように AfxTermExtensionModule をダイヤルしてください。また、アプリケーションが複数のスレッドを使用するか、動的に拡張 DLL を読み込んだら AfxLoadLibraryAfxFreeLibrary を使用してください (Win32 の代わりに LoadLibraryFreeLibraryは機能します)。AfxLoadLibraryAfxFreeLibrary を使用して拡張 DLL の読み込みまたはアンロード グローバルな MFC の状態を破損しない場合に実行する起動および終了コードがすることを保証します。

ヘッダー ファイル AFXDLLX.H は AFX_EXTENSION_MODULECDynLinkLibraryに定義のような拡張ダイナミック リンク ライブラリで使用する構造の特別な定義が含まれています。

グローバル extensionDLL は 次のように宣言する必要があります。MFC の 16 ビット バージョンとは異なり、 DllMain が呼び出されるまで MFCxx.DLL が完全に初期化されるため、メモリの割り当て、この時間の間に MFC 関数を呼び出しますできます。

hw85e4bb.collapse_all(ja-jp,VS.110).gifリソースやクラスの共有

単純な MFC 拡張ダイナミック リンク ライブラリは、クライアント アプリケーションとのみに必要な帯域幅より下位の関数をエクスポートするだけです。詳細にユーザーインターフェイスのローカライズ的な DLL は、クライアント アプリケーションにリソースと C++ クラスをエクスポートする場合があります。

リソースのエクスポートには、リソース リストを使います。各アプリケーションで CDynLinkLibrary のオブジェクトのリンク リストは単独であります。リソースを検索するときに、リソースを読み込む標準の MFC 実装の大部分は、現在のリソース モジュール (AfxGetResourceHandle)を最初に検索と取得のウォークは CDynLinkLibrary のリスト要求されたリソースを読み込むと、オブジェクトにします。

C.C++ のクラス名を持つ C++ のオブジェクトの動的生成は似ています。MFC のオブジェクトの非シリアル化の機能に基づいて必要な型の作成に再構築以前に保存された内容に動的に C++ オブジェクトをと同じように登録されている CRuntimeClass すべてのオブジェクトが必要です。

DECLARE_SERIALが、拡張 DLL でクラスを使用するクライアント アプリケーションを作成するときは、クライアント アプリケーションから参照できるようにクラスをエクスポートする必要があります。これは、調査することによって CDynLinkLibrary のリストされます。

MFC の場合は、高度な概念は、 DLLHUSKの一覧表示、またはなどのサンプル:

head ->   DLLHUSK.EXE   - or -   DLLHUSK.EXE
               |                      |
          TESTDLL2.DLL           TESTDLL2.DLL
               |                      |
          TESTDLL1.DLL           TESTDLL1.DLL
               |                      |
               |                      |
            MFC90D.DLL            MFC90.DLL

MFCxx.DLL はリソースやクラス リストの最後には、通常、あります。MFCxx.DLL は、すべての標準コマンド ID のプロンプト文字列を含む標準 MFC リソースをすべて含まれています。これをリストの割り当ての DLL と標準 MFC リソースの独自のコピーがないが、 MFCxx.DLL の共有リソースに依存するクライアント アプリケーション自体の末尾に配置します。

は、 ID または名前を選択する場合は注意が必要です。クライアント アプリケーションの名前空間へのすべての DLL のリソースとクラス名をマージすると短所があります。クライアント アプリケーションへのリソースまたは CDynLinkLibrary のオブジェクトのエクスポートなして、この機能を無効にできます。DLLHUSK サンプルでは、複数のヘッダー ファイルを使って、共有リソースの名前空間を管理します。共有リソース ファイルの使用方法に関するヒントについては、 テクニカル ノート 35 を参照してください。

hw85e4bb.collapse_all(ja-jp,VS.110).gifDLL の初期化

前述のように、通常クライアント アプリケーションにリソースやクラスをエクスポートするに CDynLinkLibrary のオブジェクトを作成する場合。DLL を初期化するエクスポート エントリ ポイントを提供する必要があります。少なくとも、これは引数を受け取りませんが何も返さない、求めてでもかまいません。無効のルーチンです。

DLL を使用する各クライアント アプリケーションはこの方法を使用すると、この初期化ルーチンをダイヤルする必要があります。また AfxInitExtensionModuleを呼び出した直後に DllMainCDynLinkLibrary のこのオブジェクトを割り当てることができます。

初期化ルーチンは、現在のアプリケーションのヒープで拡張 DLL の情報を接続するまでの CDynLinkLibrary のオブジェクト作成する必要があります。これは次にすることができます:

extern "C" extern void WINAPI InitXxxDLL()
{
   new CDynLinkLibrary(extensionDLL);
}

定期的な名前、この例の InitXxxDLL 、目的の何でもできます。これは extern "C"である必要はありませんがすると、はエクスポート リストを保持しやすくなります。

[!メモ]

レギュラー DLL から拡張 DLL を使用する場合、この初期化関数をエクスポートします。この関数は、拡張 DLL のクラスまたはリソースを使用する前にレギュラー DLL から呼び出す必要があります。

hw85e4bb.collapse_all(ja-jp,VS.110).gifエントリのエクスポート

クラスをエクスポートする最も簡単な方法は、エクスポートするグローバル関数、および各クラスの __declspec(dllimport)__declspec(dllexport) を使用することです。これは、関数をエクスポートし、序数で関数をエクスポートできるかを少なくするため、コントロールを簡単にしますが、の各エントリ ポイントを指定するよりも効率の (以下で説明)。TESTDLL1 と TESTDLL2 は、エントリをエクスポートするには、このメソッドを使用します。

効果的な方法 (および MFCxx.DLL で使用されるメソッド) .DEF ファイルの各エントリを指定することで、各エントリを手動でエクスポートします。これで、 DLL (すべて)選択的なエクスポートをエクスポートするため、どの点インターフェイスをエクスポートし、が必要かを判断する必要があります。これは、 .DEF ファイルにエントリの形式でリンカーに変形処理された名前を指定する必要があるため、困難です。実際に、のシンボリック リンクを含む必要がない場合は C++ クラスをエクスポートしないでください。

と .DEF の C++ クラスをエクスポートしての前に、ツールをこのリストを自動的に生成するために開発することのあるファイルします。これはと、リンク プロセスを使用して実行できます。DLL をエクスポートせずに一度リンクし、リンカーが .MAP ファイルを生成するようにします。.MAP ファイルがエクスポートする必要があります。再配置と、 .DEF ファイルのエクスポート エントリを生成するために使用できます。関数のリストを生成するために使用できます。数千 MFCxx.DLL と OLE、およびデータベースの拡張ダイナミック リンク ライブラリのエクスポート リストは集計では、このようなプロセス (完全に自動的にし、場合に true ハンドを必要としない)が生成されました。

hw85e4bb.collapse_all(ja-jp,VS.110).gifCWinApp 対して。CDynLinkLibrary

MFC 拡張 DLL に CWinApp- 独自の派生オブジェクトの存在がありません; 代わりに、 CWinApp- クライアント アプリケーションの派生オブジェクトを使用する必要があります。これは、クライアント アプリケーションがメイン メッセージ ポンプ、アイドル ループなど意味します。

MFC 拡張 DLL が各アプリケーション用の追加データを保持する必要がある場合 CDynLinkLibrary から新しいクラスを派生でき、それを InitXxxDLL ルーチンで作成する前に説明したします。DLL は、実行時に現在のアプリケーションの CDynLinkLibrary オブジェクト リストから特定の拡張 DLL 用のオブジェクトを探し出します。

hw85e4bb.collapse_all(ja-jp,VS.110).gifDLL の実装のリソースを使用する

前述のように、既定のリソースの負荷はリスト要求されたリソースがある最初の EXE または DLL を検索 CDynLinkLibrary のオブジェクトの走査します。存在する可能性がある場合場所でリソースを検索するすべての MFC API、すべての内部コードの使用 AfxFindResourceHandle リソース リスト。

特定の場所からリソースを読み取りのみ、古いハンドルを格納するために AfxGetResourceHandle API と AfxSetResourceHandle を使用し、新しいハンドルを設定する場合は。クライアント アプリケーションに戻る前に、元のリソース ハンドルを必ず復元してください。サンプル TESTDLL2 はメニューを明示的に読み込むには、この方法を使用します。

リストを検索する場合、多少速度が低下することとリソース ID 範囲の管理が必要なことが欠点です。複数の拡張 DLL にリンクされるクライアント アプリケーション側で、DLL のインスタンス ハンドルを指定しなくても、DLL が提供する任意のリソースを使用できるという利点もあります。AfxFindResourceHandle は、リソース リストを検索して一致するリソースを見つけるのに使われる API です。リソースの名前と型を受け取り、最初に一致したリソース ハンドル (または NULL) を返します。

DLL バージョンを使用するアプリケーションを作成できます

hw85e4bb.collapse_all(ja-jp,VS.110).gifアプリケーションの要件

MFC の共有バージョンを使用するアプリケーションは、いくつかの単純な規則に従う必要があります:

  • これは CWinApp のオブジェクトが必要で、標準に準拠するにメッセージの規則は、ポンプみます。

  • これは、一連の必須のコンパイラ フラグ (以下を参照)でコンパイルする必要があります。

  • これは、 MFCxx のインポート ライブラリとリンクする必要があります。必須のコンパイラ フラグを設定することによって、 MFC ヘッダーはライブラリのアプリケーション リンクする必要があるリンク時に決定されます。

  • 実行可能ファイルを実行するには、 MFCxx.DLL は、パスを、ウィンドウのシステム ディレクトリに置く必要があります。

hw85e4bb.collapse_all(ja-jp,VS.110).gif開発環境でビルド

標準既定のほとんどの内部メイクファイルを使用すると、簡単に DLL バージョンをビルド プロジェクトを変更できます。

次の手順では、 (デバッグ)の NAFXCWD.LIB で結合された正しく機能の MFC アプリケーションであり、として NAFXCW.LIB (リテール用)と MFC ライブラリの共有バージョンを使用するように変換する必要があります。Visual C++ の環境を実行して、内部プロジェクト ファイルがあります。

  1. プロジェクト で、メニューのをクリックします プロパティProject Defaultsの下の 一般 のページで、 Use MFC in a Shared DLL (Microsoft Foundation Class)を MFCxx (D) .dll)を設定します。

hw85e4bb.collapse_all(ja-jp,VS.110).gifNMAKE とビルド

Visual C++ メイクファイル外部の機能を使用するか、 NMAKE を直接使用すると、コンパイラとリンカー オプションをサポートするためにメイクファイルを編集する必要があります

必須のコンパイラ フラグ:

  • /D_AFXDLL /MD
    /D_AFXDLL

標準 MFC ヘッダーはこのシンボルを定義する必要があります:

  • /MD
    アプリケーションは 15 C ランタイム ライブラリの DLL バージョンを使用する必要があります。

他のコンパイラ フラグはすべて MFC の既定 (たとえば、デバッグ用の _DEBUG)に従います。

ライブラリのリンカーのリストを編集します。NAFXCWD.LIB に MFCxxD.LIB を変更し、 NAFXCW.LIB に MFCxx.LIB を変更します。MSVCRT.LIB と LIBC.LIB を置き換えます。他の MFC ライブラリと同様に MFCxxD.LIB が格納 before 、 15 C のランタイム ライブラリにすることが重要です。

オプションで /D_AFXDLL をリテールに追加し、リソース コンパイラ オプション (実際に /Rのリソースをコンパイルする 1)をデバッグします。これは、 MFC DLL にあるリソースを共有すると、最終的で実行可能な小さいのようになります。

完全なリビルドは次の変更が行われた後で必要です。

hw85e4bb.collapse_all(ja-jp,VS.110).gifサンプルをビルド

MFC のサンプル プログラムのほとんどは、 Visual C++ またはコマンド ラインから共有 NMAKE 互換のメイクファイルからビルドできます。

MFCxx.DLL を使用すると、のこれらのサンプル変換するには、 Visual C++ に .MAK ファイルを読み取り、プロジェクト オプションを既に説明したように構成できます。NMAKE のビルドを使用する場合、 NMAKE のコマンド ラインで 「」 AFXDLL=1 を指定し、 MFC 共有ライブラリを使用するサンプルをビルドします。

MFC の高度な概念のサンプル DLLHUSK は、 MFC DLL バージョンを使ってビルドされます。このサンプルは MFCxx.DLL で結合されたアプリケーションのみをビルド方法については説明しませんもこのテクニカル ノートの後半で説明する MFC 拡張ダイナミック リンク ライブラリなどの MFC DLL のパッケージ オプションの他の機能について説明します。

hw85e4bb.collapse_all(ja-jp,VS.110).gifパッケージのメモ

DLL (MFCxx [U] .DLL)のリテール バージョンの再配布は自由です。DLL のデバッグ バージョンは自由に再配布できません。また、アプリケーションの開発時にだけ使用します。

デバッグ DLL をデバッグ情報が与えられます。Visual C++ デバッガーを使用して、アプリケーション、または DLL の実行をトレースできます。リリース DLL (MFCxx [U] .DLL)はデバッグ情報が含まれません。

または再ビルドした DLL をカスタマイズする場合は、 「MFCxx 以外の方法でそれらをダイヤルする必要があります」。 MFC のソース ファイル MFCDLL.MAK がビルド オプションについて説明し、 DLL の名前を変更するためのロジックを含む。ファイルの名前を変更すると、これらの DLL が多くの MFC アプリケーションに、共有されるため、必要です。MFC DLL のカスタム バージョンを持っているシステムにインストールされる機能を共有 MFC DLL を使用して別の MFC アプリケーションが破損するおそれで置き換えます。

MFC DLL をビルドし直すことはお勧めしません。

MFCxx.DLL を実行する方法

以降のセクションでは、 MFC DLL (MFCxx.DLL と MFCxxD.DLL)の実装方法について説明します。理解して次の詳細は、がするのがアプリケーションの MFC DLL を使用するだけの場合は重要ではありません。ここでは詳しく理解するために MFC 拡張 DLL の作成方法ではありません。 DLL を作成するにはこの実装を理解することが記述するのに役立つ場合があります。

hw85e4bb.collapse_all(ja-jp,VS.110).gif実装の概要

MFC DLL は実際に MFC 拡張 DLL の上記と特殊なケースです。それに多数のクラスの非常に多くのエクスポートがあります。いくつかの追加処理がありますが、をさらに特別にする、通常の拡張 DLL で MFC DLL にする。

hw85e4bb.collapse_all(ja-jp,VS.110).gifWin32 はほとんどの作業します

MFC の 16 ビット バージョンは 80x86 アセンブリ コードによって、プロセスごとの例外コンテキスト作成されたスタック セグメント、特別なセグメントと他の手法の、アプリケーションのデータを含めるいくつかの特殊な手法が必要です。Win32 には直接である DLL ごとのプロセスのデータがサポートされています。ほとんどの場合、目的が。主として MFCxx.DLL は DLL にパッケージ化、 NAFXCW.LIB です。MFC ソース・コードを調べると、非常に対して行う必要があるいくつかの特殊なケースであるため、いくつかの _AFXDLL #ifdef を検索します。そこである特殊なケースは、 Windows 3.1 の Win32 を処理することです (Win32s として知られています)。Win32s は、プロセスの DLL のデータを直接サポートしていません。 MFC DLL は、プロセス ローカル データの取得にスレッドローカル ストレージの (TLS) の Win32 API を使用する必要があります。

hw85e4bb.collapse_all(ja-jp,VS.110).gifライブラリ ソース ファイル、追加の影響

通常の MFC クラス ライブラリ ソースおよびヘッダーの _AFXDLL バージョンの影響は比較的小さなです。特殊なバージョンのファイル (AFXV_DLL.H)、およびそのほかのヘッダー ファイルがあります (AFXDLL_.H)メイン AFXWIN.H ヘッダーに含まれています。AFXDLL_.H ヘッダーは両方 _AFXDLL アプリケーションや MFC のダイナミック リンク ライブラリの拡張 CDynLinkLibrary のクラスおよびそのほかの実装の詳細が含まれています。AFXDLLX.H ヘッダーは、 MFC 拡張ダイナミック リンク ライブラリをビルドするに提供されます。詳細については、前の " " を参照してください)。

MFC のソースの MFC ライブラリへの通常のソースに _AFXDLL の #ifdef の下に追加条件付きのコードがあります。追加ソース ファイル (DLLINIT.CPP)は、 MFC の共有バージョンの追加の DLL の初期化コードと他の接着が含まれます。

MFC の共有バージョンをビルドするには、追加ファイルが用意されています。(DLL をビルド方法の詳細については、次を参照)。

  • 2 個の .DEF ファイルはデバッグ MFCxxD.DEF ()の MFC DLL のエントリ ポイントをエクスポートするために使用されます (DLL)の MFCxx.DEF バージョンを解放します。

  • .RC ファイル (MFCDLL.RC)は、 DLL のすべての標準 MFC リソースと VERSIONINFO のリソースが含まれます。

  • .CLW ファイル (MFCDLL.CLW)は ClassWizard を使用して MFC クラスを参照できるように用意されています。メモ: この機能は、 MFC DLL バージョンに固有ではありません。

hw85e4bb.collapse_all(ja-jp,VS.110).gifメモリ管理

MFCxx.DLL を使用してアプリケーションは MSVCRTxx.DLL によって提供される共通のメモリ アロケーター共有 15 C ランタイムの DLL を使用します。アプリケーションは、 MFC DLL 自体として拡張ダイナミック リンク ライブラリとしておいてください。この共有メモリのアロケーターを使用します。メモリ割り当てに共有 DLL を使用することによって、 MFC DLL では、アプリケーションによってその逆に解放されたメモリを割り当てることができます。アプリケーションと DLL の両方が同じアロケーターを使用する必要があるため、 C++ グローバル operator newoperator deleteをオーバーライドしないでください。同じ規則が 15 C ランタイムのメモリ割り当てルーチンの他に適用されます ( mallocreallocfree、などの)。

hw85e4bb.collapse_all(ja-jp,VS.110).gif序数、およびクラスの __declspec (dllexport)と DLL の名前

ここでは、 C++ コンパイラの class**__declspec(dllexport)** の機能を使用しません。代わりに、エクスポートの一覧は、クラス ライブラリ ソースに含まれています (MFCxx.DEF と MFCxxD.DEF)。通常、これらのエントリ ポイントの設定を選択します (関数とデータ)エクスポートされます。他のシンボルは、 MFC のプライベート実装の関数やクラスなど、または名前非常駐テーブルの文字列名を指定せずに序数で、すべてのエクスポートされるエクスポートされません。

classを使用するよりも小さい DLL をビルドするの実行可能な選択肢に、 MFC などの大きな DLL の場合は、関数をエクスポートする既定の効率と容量の制限があります。

すべてのメジャーが、多くの実行が損なわれる場合、または速度を読み込んだり、 (約 800 KB であるリリース MFCxx.DLL の大量の機能をパッケージ化することもできることです。この操作は。MFCxx.DLL は、より大きな KB この手法使用されていません。これは、ファイルするように、 .DEF の末尾に追加エントリ ポイントを追加するように序数によるエクスポートの速度とサイズの効率を損なうことなく、単純なバージョン管理を許可するようにします。MFC クラス ライブラリのメジャー バージョンのリビジョンは、ライブラリ名を変更します。つまり、 MF C30 .DLL は、 MFC クラス ライブラリのバージョン 3.0 を含む DLL 再頒布可能です。架空の MFC 3.1 でこの DLL のアップグレードは、 DLL MF C31 .DLL はなくという名前になります。再度 MFC DLL のカスタム バージョンを生成するために MFC ソース・コードを変更する場合は異なる名前を使用します (および名前に 「MFC」なしの場合は 1 番)。

参照

その他の技術情報

番号順テクニカル ノート

カテゴリ別テクニカル ノート