DLL と Visual C++ ランタイム ライブラリの動作DLLs and Visual C++ run-time library behavior

Visual Studio を使用してダイナミックリンク ライブラリ (DLL) をビルドする場合、既定では、リンカーには Visual C++ ランタイム ライブラリ (VCRuntime) が含まれます。When you build a Dynamic-link Library (DLL) by using Visual Studio, by default, the linker includes the Visual C++ run-time library (VCRuntime). VCRuntime には、C/C++ 実行可能ファイルを初期化および終了するために必要なコードが含まれています。The VCRuntime contains code required to initialize and terminate a C/C++ executable. DLL にリンクされる場合、VCRuntime コードは _DllMainCRTStartup と呼ばれる内部 DLL エントリポイント関数を提供します。この関数は、Windows OS メッセージを DLL に渡してプロセスまたはスレッドにアタッチまたはデタッチします。When linked into a DLL, the VCRuntime code provides an internal DLL entry-point function called _DllMainCRTStartup that handles Windows OS messages to the DLL to attach to or detach from a process or thread. _DllMainCRTStartup 関数は、スタック バッファー セキュリティのセットアップ、C ランタイム ライブラリ (CRT) の初期化と終了、静的オブジェクトとグローバル オブジェクトのコンストラクターとデストラクターの呼び出しなど、重要なタスクを実行します。The _DllMainCRTStartup function performs essential tasks such as stack buffer security set up, C run-time library (CRT) initialization and termination, and calls to constructors and destructors for static and global objects. _DllMainCRTStartup は、WinRT、MFC、ATL などの他のライブラリのフック関数も呼び出して、独自の初期化と終了を実行します。_DllMainCRTStartup also calls hook functions for other libraries such as WinRT, MFC, and ATL to perform their own initialization and termination. この初期化がないと、CRT とその他のライブラリ、および静的変数は初期化されていない状態のままになります。Without this initialization, the CRT and other libraries, as well as your static variables, would be left in an uninitialized state. DLL が静的にリンクされた CRT を使用するか、動的にリンクされた CRT DLL を使用するかにかかわらず、同じ VCRuntime 内部初期化および終了ルーチンが呼び出されます。The same VCRuntime internal initialization and termination routines are called whether your DLL uses a statically linked CRT or a dynamically linked CRT DLL.

既定の DLL エントリ ポイント _DllMainCRTStartupDefault DLL entry point _DllMainCRTStartup

Windows では、すべての DLL にオプションのエントリ ポイント関数 (通常、DllMain) が含まれます。エントリ ポイント関数は、初期化と終了の両方で呼び出されます。In Windows, all DLLs can contain an optional entry-point function, usually called DllMain, that is called for both initialization and termination. これによって、追加のリソースを必要に応じて、割り当て/解放する機会が与えられます。This gives you an opportunity to allocate or release additional resources as needed. Windows には、エントリ ポイント関数が呼び出される 4 つの状況 (プロセスのアタッチ、プロセス デタッチ、スレッド アタッチ、スレッド デタッチ) があります。Windows calls the entry-point function in four situations: process attach, process detach, thread attach, and thread detach. DLL がプロセス アドレス空間に読み込まれると、その DLL を使用するアプリケーションが読み込まれたとき、またはアプリケーションが実行時に DLL を要求したときに、オペレーティング システムによって DLL データのコピーが個別に作成されます。When a DLL is loaded into a process address space, either when an application that uses it is loaded, or when the application requests the DLL at runtime, the operating system creates a separate copy of the DLL data. これは プロセスのアタッチ と呼ばれます。This is called process attach. スレッドのアタッチ は、DLL が読み込まれるプロセスによって新しいスレッドが作成されるときに発生します。Thread attach occurs when the process the DLL is loaded in creates a new thread. スレッドのデタッチ はスレッドが終了するときに発生し、プロセスのデタッチ は DLL が不要になり、アプリケーションによって解放されるときに発生します。Thread detach occurs when the thread terminates, and process detach is when the DLL is no longer required and is released by an application. オペレーティング システムは、これらの各イベントの DLL エントリ ポイントを個別に呼び出し、各イベントの種類に対して reason 引数を渡します。The operating system makes a separate call to the DLL entry point for each of these events, passing a reason argument for each event type. たとえば、OS は DLL_PROCESS_ATTACHreason 引数として送信し、プロセスのアタッチを通知します。For example, the OS sends DLL_PROCESS_ATTACH as the reason argument to signal process attach.

VCRuntime ライブラリには、既定の初期化および終了操作を処理するために _DllMainCRTStartup というエントリポイント関数が用意されています。The VCRuntime library provides an entry-point function called _DllMainCRTStartup to handle default initialization and termination operations. プロセスのアタッチでは、_DllMainCRTStartup 関数は、バッファー セキュリティ チェックを設定し、CRT とその他のライブラリを初期化し、ランタイム型情報を初期化し、静的および非ローカルのデータのコンストラクターを初期化して呼び出し、スレッドローカル ストレージを初期化し、アタッチごとに内部静的カウンターをインクリメントしてから、ユーザーまたはライブラリが提供する DllMain を呼び出します。On process attach, the _DllMainCRTStartup function sets up buffer security checks, initializes the CRT and other libraries, initializes run-time type information, initializes and calls constructors for static and non-local data, initializes thread-local storage, increments an internal static counter for each attach, and then calls a user- or library-supplied DllMain. プロセスのデタッチでは、関数はこれらのステップを逆順で実行します。On process detach, the function goes through these steps in reverse. DllMain を呼び出し、内部カウンターをデクリメントし、デストラクターを呼び出し、CRT 終了関数と登録済み atexit 関数を呼び出し、他のすべてのライブラリが終了したことを通知します。It calls DllMain, decrements the internal counter, calls destructors, calls CRT termination functions and registered atexit functions, and notifies any other libraries of termination. アタッチカウンターが 0 になると、関数は FALSE を返して、DLL をアンロードできることを Windows に示します。When the attachment counter goes to zero, the function returns FALSE to indicate to Windows that the DLL can be unloaded. _DllMainCRTStartup 関数は、スレッドのアタッチとスレッドのデタッチ中にも呼び出されます。The _DllMainCRTStartup function is also called during thread attach and thread detach. このような場合、VCRuntime コードは追加の初期化も終了も行わず、DllMain を呼び出してメッセージを渡すだけです。In these cases, the VCRuntime code does no additional initialization or termination on its own, and just calls DllMain to pass the message along. DllMain がプロセスのアタッチから FALSE を返した場合、通知は失敗し、_DllMainCRTStartupDllMain を再度呼び出して DLL_PROCESS_DETACHreason 引数として渡してから、終了処理の残りを実行します。If DllMain returns FALSE from process attach, signaling failure, _DllMainCRTStartup calls DllMain again and passes DLL_PROCESS_DETACH as the reason argument, then goes through the rest of the termination process.

Visual Studio で Dll をビルドする場合、VCRuntime によって提供される既定のエントリ ポイント _DllMainCRTStartup が自動的にリンクされます。When building DLLs in Visual Studio, the default entry point _DllMainCRTStartup supplied by VCRuntime is linked in automatically. /ENTRY (エントリ ポイント シンボル) リンカー オプションを使用して、DLL のエントリポイント関数を指定する必要はありません。You do not need to specify an entry-point function for your DLL by using the /ENTRY (Entry point symbol) linker option.

注意

/ENTRY: リンカー オプションを使うと DLL の別のエントリ ポイント関数を指定できますが、そのエントリポイント関数では _DllMainCRTStartup が行う全処理を同じ順序で繰り返す必要があるため、この方法は推奨できません。While it is possible to specify another entry-point function for a DLL by using the /ENTRY: linker option, we do not recommend it, because your entry-point function would have to duplicate everything that _DllMainCRTStartup does, in the same order. VCRuntime には、その動作を複製できるようにする関数が用意されています。The VCRuntime provides functions that allow you to duplicate its behavior. たとえば、プロセスのアタッチですぐに __security_init_cookie を呼び出して、/GS (バッファー セキュリティ チェック) バッファー チェック オプションをサポートすることができます。For example, you can call __security_init_cookie immediately on process attach to support the /GS (Buffer security check) buffer checking option. _CRT_INIT 関数を呼び出して、エントリ ポイント関数と同じパラメーターを渡すことにより、DLL 初期化関数または終了関数の残りを実行できます。You can call the _CRT_INIT function, passing the same parameters as the entry point function, to perform the rest of the DLL initialization or termination functions.

DLL の初期化Initialize a DLL

DLL の読み込み時に実行する必要がある初期化コードが DLL に含まれている可能性があります。Your DLL may have initialization code that must execute when your DLL loads. 独自の DLL 初期化関数と終了関数を実行するために、_DllMainCRTStartup は、指定できる DllMain と呼ばれる関数を呼び出します。In order for you to perform your own DLL initialization and termination functions, _DllMainCRTStartup calls a function called DllMain that you can provide. DllMain には、DLL エントリ ポイントに要求されるシグネチャが必要です。Your DllMain must have the signature required for a DLL entry point. 既定のエントリ ポイント関数 _DllMainCRTStartup は、Windows によって渡される同じパラメーターを使用して DllMain を呼び出します。The default entry point function _DllMainCRTStartup calls DllMain using the same parameters passed by Windows. 既定では、DllMain 関数を指定しない場合、Visual Studio によってその関数が提供され、_DllMainCRTStartup に常に呼び出し対象が含まれるようにリンクが設定されます。By default, if you do not provide a DllMain function, Visual Studio provides one for you and links it in so that _DllMainCRTStartup always has something to call. つまり、DLL を初期化する必要がない場合、DLL のビルド時に必要な処理は特にありません。This means that if you do not need to initialize your DLL, there is nothing special you have to do when building your DLL.

これは DllMain に使用されるシグネチャです。This is the signature used for DllMain:

#include <windows.h>

extern "C" BOOL WINAPI DllMain (
    HINSTANCE const instance,  // handle to DLL module
    DWORD     const reason,    // reason for calling function
    LPVOID    const reserved); // reserved

一部のライブラリでは、DllMain 関数がラップされています。Some libraries wrap the DllMain function for you. たとえば、標準の MFC DLL では、CWinApp オブジェクトの InitInstance および ExitInstance メンバー関数を実装して、DLL で必要な初期化と終了を実行します。For example, in a regular MFC DLL, implement the CWinApp object's InitInstance and ExitInstance member functions to perform initialization and termination required by your DLL. 詳細については、「標準 MFC DLL の初期化」セクションを参照してください。For more details, see the Initialize regular MFC DLLs section.

警告

DLL のエントリ ポイントで安全に実行できる処理には大きな制限があります。There are significant limits on what you can safely do in a DLL entry point. DllMain での呼び出しが安全ではない特定の Windows API については、一般的なベスト プラクティスに関するページを参照してください。See General Best Practices for specific Windows APIs that are unsafe to call in DllMain. 最も単純な初期化以外にも必要である場合は、DLL の初期化関数でそれを実行します。If you need anything but the simplest initialization then do that in an initialization function for the DLL. DllMain が実行された後、DLL 内の他の関数を呼び出す前に、アプリケーションが初期化関数を呼び出すように要求することができます。You can require applications to call the initialization function after DllMain has run and before they call any other functions in the DLL.

通常 (非 MFC) DLL の初期化Initialize ordinary (non-MFC) DLLs

VCRuntime によって提供される _DllMainCRTStartup エントリ ポイントを使用する通常の (非 MFC) DLL で独自の初期化を実行するには、DLL ソース コードに DllMain という名前の関数が含まれている必要があります。To perform your own initialization in ordinary (non-MFC) DLLs that use the VCRuntime-supplied _DllMainCRTStartup entry point, your DLL source code must contain a function called DllMain. 次のコードは、DllMain の定義がどのようなものかを示す基本的なスケルトンを示しています。The following code presents a basic skeleton showing what the definition of DllMain might look like:

#include <windows.h>

extern "C" BOOL WINAPI DllMain (
    HINSTANCE const instance,  // handle to DLL module
    DWORD     const reason,    // reason for calling function
    LPVOID    const reserved)  // reserved
{
    // Perform actions based on the reason for calling.
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        // Initialize once for each new process.
        // Return FALSE to fail DLL load.
        break;

    case DLL_THREAD_ATTACH:
        // Do thread-specific initialization.
        break;

    case DLL_THREAD_DETACH:
        // Do thread-specific cleanup.
        break;

    case DLL_PROCESS_DETACH:
        // Perform any necessary cleanup.
        break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

注意

以前の Windows SDK ドキュメントでは、/ENTRY オプションを使用して、リンカー コマンドラインに DLL エントリポイント関数の実際の名前を指定する必要があることが示されています。Older Windows SDK documentation says that the actual name of the DLL entry-point function must be specified on the linker command-line with the /ENTRY option. Visual Studio では、エントリポイント関数の名前が DllMain である場合、/ENTRY オプションを使用する必要はありません。With Visual Studio, you do not need to use the /ENTRY option if the name of your entry-point function is DllMain. 実際に、/ENTRY オプションを使用してエントリポイント関数に DllMain 以外の名前を指定した場合、エントリポイント関数によって _DllMainCRTStartup と同じ初期化呼び出しが行われない限り、CRT は適切に初期化されません。In fact, if you use the /ENTRY option and name your entry-point function something other than DllMain, the CRT does not get initialized properly unless your entry-point function makes the same initialization calls that _DllMainCRTStartup makes.

標準 MFC DLL の初期化Initialize regular MFC DLLs

標準 MFC Dll には CWinApp オブジェクトがあるので、MFC アプリケーションと同じ場所、つまり DLL の CWinApp 派生クラスの InitInstance および ExitInstance メンバー関数で初期化タスクと終了タスクを実行する必要があります。Because regular MFC DLLs have a CWinApp object, they should perform their initialization and termination tasks in the same location as an MFC application: in the InitInstance and ExitInstance member functions of the DLL's CWinApp-derived class. MFC には DLL_PROCESS_ATTACHDLL_PROCESS_DETACH_DllMainCRTStartup によって呼び出される DllMain 関数が用意されているため、独自の DllMain 関数を記述することは避けてください。Because MFC provides a DllMain function that is called by _DllMainCRTStartup for DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH, you should not write your own DllMain function. MFC に用意されている DllMain 関数は、DLL が読み込まれるときに InitInstance を呼び出し、DLL がアンロードされる前に ExitInstance を呼び出します。The MFC-provided DllMain function calls InitInstance when your DLL is loaded and it calls ExitInstance before the DLL is unloaded.

標準 MFC DLL では、その InitInstance 関数で TlsAlloc および TlsGetValue を呼び出すことで、複数のスレッドを追跡できます。A regular MFC DLL can keep track of multiple threads by calling TlsAlloc and TlsGetValue in its InitInstance function. これらの関数により、DLL がスレッド固有のデータを追跡できます。These functions allow the DLL to track thread-specific data.

MFC に動的にリンクする標準 MFC DLL 内で MFC OLE、MFC データベース (または DAO)、または MFC ソケットのサポートを使用している場合は、それぞれデバッグ MFC 拡張 DLL の MFCO version D.dll、MFCD version D.dll、および MFCN version D.dll (version はバージョン番号) が自動的にリンクされます。In your regular MFC DLL that dynamically links to MFC, if you are using any MFC OLE, MFC Database (or DAO), or MFC Sockets support, respectively, the debug MFC extension DLLs MFCO version D.dll, MFCD version D.dll, and MFCN version D.dll (where version is the version number) are linked in automatically. 標準 MFC DLL の CWinApp::InitInstance で使用している DLL ごとに、次の定義済み初期化関数のいずれかを呼び出す必要があります。You must call one of the following predefined initialization functions for each of these DLLs that you are using in your regular MFC DLL's CWinApp::InitInstance.

MFC サポートの種類Type of MFC support 呼び出す初期化関数Initialization function to call
MFC OLE (MFCO version D.dll)MFC OLE (MFCO version D.dll) AfxOleInitModule
MFC データベース (MFCD version D.dll)MFC Database (MFCD version D.dll) AfxDbInitModule
MFC ソケット (MFCN version D.dll)MFC Sockets (MFCN version D.dll) AfxNetInitModule

MFC 拡張 DLL の初期化Initialize MFC extension DLLs

MFC 拡張 DLL には CWinApp 派生オブジェクトがないため (標準 MFC DLL にはあります)、MFC DLL ウィザードによって生成される DllMain 関数に初期化コードと終了コードを追加する必要があります。Because MFC extension DLLs do not have a CWinApp-derived object (as do regular MFC DLLs), you should add your initialization and termination code to the DllMain function that the MFC DLL Wizard generates.

ウィザードには、MFC 拡張 DLL 用の次のコードが用意されています。The wizard provides the following code for MFC extension DLLs. コードで、PROJNAME はプロジェクト名のプレースホルダーです。In the code, PROJNAME is a placeholder for the name of your project.

#include "pch.h" // For Visual Studio 2017 and earlier, use "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;

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
   if (dwReason == DLL_PROCESS_ATTACH)
   {
      TRACE0("PROJNAME.DLL Initializing!\n");

      // MFC 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 オブジェクトを作成すると、MFC 拡張 DLL がクライアント アプリケーションに CRuntimeClass オブジェクトまたはリソースをエクスポートできます。Creating a new CDynLinkLibrary object during initialization allows the MFC extension DLL to export CRuntimeClass objects or resources to the client application.

1 つ以上の標準 MFC DLL から MFC 拡張 DLL を使用する場合は、CDynLinkLibrary オブジェクトを作成する初期化関数をエクスポートする必要があります。If you are going to use your MFC extension DLL from one or more regular MFC DLLs, you must export an initialization function that creates a CDynLinkLibrary object. その関数は、MFC 拡張 DLL を使用するそれぞれの標準 MFC DLL から呼び出す必要があります。That function must be called from each of the regular MFC DLLs that use the MFC extension DLL. この初期化関数を呼び出す適切な場所は、標準 MFC DLL の CWinApp 派生オブジェクトの InitInstance メンバー関数内で、MFC 拡張 DLL のエクスポートされたクラスまたは関数のいずれかを使用する前です。An appropriate place to call this initialization function is in the InitInstance member function of the regular MFC DLL's CWinApp-derived object before using any of the MFC extension DLL's exported classes or functions.

MFC DLL ウィザードによって生成される DllMain では、AfxInitExtensionModule を呼び出すことによって、モジュールの実行時クラス (CRuntimeClass 構造体) だけでなく、CDynLinkLibrary オブジェクトの作成時に使用するオブジェクト ファクトリ (COleObjectFactory オブジェクト) がキャプチャされます。In the DllMain that the MFC DLL Wizard generates, the call to AfxInitExtensionModule captures the module's run-time classes (CRuntimeClass structures) as well as its object factories (COleObjectFactory objects) for use when the CDynLinkLibrary object is created. AfxInitExtensionModule の戻り値を確認する必要があります。AfxInitExtensionModule から 0 の値が返された場合は、DllMain 関数から 0 を返します。You should check the return value of AfxInitExtensionModule; if a zero value is returned from AfxInitExtensionModule, return zero from your DllMain function.

MFC 拡張 DLL が実行可能ファイルに明示的にリンクされている場合 (つまり、実行可能ファイルが AfxLoadLibrary を呼び出して DLL にリンクする場合)、DLL_PROCESS_DETACHAfxTermExtensionModule の呼び出しを追加する必要があります。If your MFC extension DLL will be explicitly linked to an executable (meaning the executable calls AfxLoadLibrary to link to the DLL), you should add a call to AfxTermExtensionModule on DLL_PROCESS_DETACH. この関数を使用すると、各プロセスが MFC 拡張 DLL からデタッチされたときに MFC 拡張 DLL をクリーンアップできます (デタッチは、プロセスが終了したとき、または DLL が AfxFreeLibrary 呼び出しの結果としてアンロードされたときに発生します)。This function allows MFC to clean up the MFC extension DLL when each process detaches from the MFC extension DLL (which happens when the process exits or when the DLL is unloaded as a result of a AfxFreeLibrary call). MFC 拡張 DLL がアプリケーションに暗黙的にリンクされる場合、AfxTermExtensionModule の呼び出しは必要ありません。If your MFC extension DLL will be linked implicitly to the application, the call to AfxTermExtensionModule is not necessary.

MFC 拡張 DLL に明示的にリンクするアプリケーションは、DLL を解放するときに AfxTermExtensionModule を呼び出す必要があります。Applications that explicitly link to MFC extension DLLs must call AfxTermExtensionModule when freeing the DLL. また、アプリケーションで複数のスレッドが使用されている場合は、(Win32 関数 LoadLibrary および FreeLibrary ではなく) AfxLoadLibrary および AfxFreeLibrary も使用する必要があります。They should also use AfxLoadLibrary and AfxFreeLibrary (instead of the Win32 functions LoadLibrary and FreeLibrary) if the application uses multiple threads. AfxLoadLibraryAfxFreeLibrary を使用すると、MFC 拡張 DLL がロードおよびアンロードされたときに実行される起動コードとシャットダウン コードが、グローバルの MFC 状態を破壊することがなくなります。Using AfxLoadLibrary and AfxFreeLibrary ensures that the startup and shutdown code that executes when the MFC extension DLL is loaded and unloaded does not corrupt the global MFC state.

MFCx0.dll は DllMain が呼び出された時点で完全に初期化されるので、DllMain 内でメモリを割り当て、MFC 関数を呼び出すことができます (16 ビット バージョンの MFC とは異なります)。Because the MFCx0.dll is fully initialized by the time DllMain is called, you can allocate memory and call MFC functions within DllMain (unlike the 16-bit version of MFC).

拡張 DLL では、DllMain 関数内の DLL_THREAD_ATTACH および DLL_THREAD_DETACH ケースを処理することによって、マルチスレッド処理を行うことができます。Extension DLLs can take care of multithreading by handling the DLL_THREAD_ATTACH and DLL_THREAD_DETACH cases in the DllMain function. これらのケースは、スレッドが DLL に対してアタッチおよびデタッチするときに DllMain に渡されます。These cases are passed to DllMain when threads attach and detach from the DLL. DLL がアタッチされているときに TlsAlloc を呼び出すと、DLL にアタッチされているすべてのスレッドに対して、DLL はスレッド ローカル ストレージ (TLS) インデックスを維持できます。Calling TlsAlloc when a DLL is attaching allows the DLL to maintain thread local storage (TLS) indexes for every thread attached to the DLL.

ヘッダー ファイル Afxdllx.h には、MFC 拡張 DLL で使用される構造体の特別な定義 (AFX_EXTENSION_MODULE および CDynLinkLibrary の定義など) が含まれていることに注意してください。Note that the header file Afxdllx.h contains special definitions for structures used in MFC extension DLLs, such as the definition for AFX_EXTENSION_MODULE and CDynLinkLibrary. このヘッダー ファイルは、MFC 拡張 DLL に含める必要があります。You should include this header file in your MFC extension DLL.

注意

重要なのは、pch.h (Visual Studio 2017 以前では stdafx.h) で _AFX_NO_XXX マクロを定義したり未定義にしたりすることができないことです。It is important that you neither define nor undefine any of the _AFX_NO_XXX macros in pch.h (stdafx.h in Visual Studio 2017 and earlier). これらのマクロは、特定のターゲット プラットフォームでその機能がサポートされているかどうかを確認するためだけに存在します。These macros exist only for the purpose of checking whether a particular target platform supports that feature or not. これらのマクロをチェックするようにプログラムを記述できます (たとえば、#ifndef _AFX_NO_OLE_SUPPORT)。ただし、プログラムでこれらのマクロを定義または未定義にすることはできません。You can write your program to check these macros (for example, #ifndef _AFX_NO_OLE_SUPPORT), but your program should never define or undefine these macros.

マルチスレッド処理を行うサンプルの初期化関数は、Windows SDK のダイナミックリンク ライブラリでスレッド ローカル ストレージを使用する方法に関するページに含まれています。A sample initialization function that handles multithreading is included in Using Thread Local Storage in a Dynamic-Link Library in the Windows SDK. このサンプルには LibMain というエントリポイント関数が含まれていますが、MFC および C ランタイム ライブラリで動作するように、この関数の名前を DllMain にする必要があります。Note that the sample contains an entry-point function called LibMain, but you should name this function DllMain so that it works with the MFC and C run-time libraries.

関連項目See also

Visual Studio での C/C++ Dll の作成Create C/C++ DLLs in Visual Studio
DllMain エントリ ポイントDllMain entry point
ダイナミックリンク ライブラリのベスト プラクティスDynamic-link Library Best Practices