次の方法で共有


拡張 DLL の初期化

拡張 DLL には、CWinApp 派生オブジェクトがないため、MFC DLL ウィザード が生成する DllMain 関数に対する初期化コードと終了コードを追加する必要があります。

ウィザードは、拡張 DLL 用に次のコードを提供します。 次のコードにある PROJNAME は、プロジェクト名のプレースホルダーです。

#include "stdafx.h"
#include <afxdllx.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static AFX_EXTENSION_MODULE PROJNAMEDLL = { NULL, NULL };

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
   if (dwReason == DLL_PROCESS_ATTACH)
   {
      TRACE0("PROJNAME.DLL Initializing!\n");
      
      // Extension DLL one-time initialization
      AfxInitExtensionModule(PROJNAMEDLL, 
                                 hInstance);

      // Insert this DLL into the resource chain
      new CDynLinkLibrary(Dll3DLL);
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
      TRACE0("PROJNAME.DLL Terminating!\n");
   }
   return 1;   // ok
}

初期化時に新しい CDynLinkLibrary オブジェクトを作成することによって、拡張 DLL は CRuntimeClass オブジェクトやリソースをクライアント アプリケーションにエクスポートできます。

拡張 DLL を 1 つ以上のレギュラー DLL から使う予定がある場合、CDynLinkLibrary オブジェクトを作成する初期化関数をエクスポートする必要があります。 初期化関数の呼び出しは、拡張 DLL を使う各レギュラー DLL から行います。 初期化関数の呼び出しに適した場所は、拡張 DLL のエクスポート クラスまたはエクスポート関数を使う前の、レギュラー DLL の CWinApp 派生オブジェクトの InitInstance メンバー関数の中です。

MFC DLL ウィザード が生成する DllMain では、CDynLinkLibrary が作成されたときのために、AfxInitExtensionModule を呼び出すと、オブジェクト ファクトリ (COleObjectFactory オブジェクト) とモジュールのランタイム クラス (CRuntimeClass 構造体) がキャプチャされます。 また、AfxInitExtensionModule の戻り値を調べる必要があります。AfxInitExtensionModule から値 0 が返されると、DllMain 関数から 0 を返します。

拡張 DLL が実行形式と明示的にリンクされる場合 (つまり、実行形式が AfxLoadLibrary を呼び出して DLL にリンクする場合)、DLL_PROCESS_DETACH には AfxTermExtensionModule の呼び出しを追加する必要があります。 MFC はこの関数を使って、各プロセスが拡張 DLL からデタッチするときに、拡張 DLL をクリアします。プロセスのデタッチは、AfxFreeLibrary によって DLL がアンロードされるときか、プロセスが終了するときに発生します。 拡張 DLL がアプリケーションと暗黙的にリンクされる場合、AfxTermExtensionModule への呼び出しは不要です。

DLL と明示的にリンクするアプリケーションは、DLL を解放する時点で AfxTermExtensionModule を呼び出す必要があります。 また、これらのアプリケーションが複数のスレッドを使う場合は、Win32 関数の LoadLibraryFreeLibrary ではなく、AfxLoadLibraryAfxFreeLibrary を使います。 AfxLoadLibraryAfxFreeLibrary を使用することによって、拡張 DLL の読み込みまたはアンロード時に実行されるスタートアップ コードと終了コードが、グローバルな MFC の状態を破損するのを防ぎます。

16 ビット版の MFC とは異なり、DllMain が呼び出される時点までに MFCx0.dll は完全に初期化されているので、DllMain でメモリの割り当てや MFC 関数の呼び出しを行うことができます。

拡張 DLL は、DllMain 関数内で DLL_THREAD_ATTACHDLL_THREAD_DETACH の分岐を処理することによって、マルチスレッドを扱うことができます。 これらの分岐は、スレッドと DLL のアタッチ/デタッチ時に DllMain に渡されます。 DLL のアタッチ時に TlsAlloc を呼び出すことによって、DLL は、アタッチされる各スレッドの TLS (スレッド ローカル ストレージ) インデックスを管理します。

ヘッダー ファイル Afxdllx.h には、AFX_EXTENSION_MODULECDynLinkLibrary などの拡張 DLL で使われる構造体の特別な定義が含まれています。 このヘッダー ファイルを拡張 DLL にインクルードする必要があります。

注意

Stdafx.h 内の _AFX_NO_XXX マクロについては、定義/定義解除を行わないことが重要です。 詳細については、サポート技術情報の「PRB: Problems Occur When Defining _AFX_NO_XXX (Q140751)」を参照してください。 サポート技術情報の文書は、MSDN ライブラリまたは https://support.microsoft.com/ で参照できます。

マルチスレッドを処理する初期化関数のサンプルは、Windows SDK の「Using Thread Local Storage in a Dynamic-Link Library」に含まれています。 このサンプルでは、LibMain というエントリ ポイント関数が使われていますが、MFC および C ランタイム ライブラリで実行するためには、この関数を DllMain と置き換える必要があります。

MFC のサンプル DLLHUSK では、初期化関数の使い方が説明されています。

目的に合ったトピックをクリックしてください

さらに詳しくは次のトピックをクリックしてください

参照

概念

DLL の初期化