Initialize Extension DLLs
| Overview | How Do I | FAQ | Details | Sample
Because extension DLLs do not have a CWinApp-derived object (as do regular DLLs), you should add your initialization and termination code to the DllMain function that AppWizard generates.
AppWizard provides the following code for extension DLLs. In the code below, PROJNAME
is a placeholder for the name of your project.
#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
}
Creating a new CDynLinkLibrary object during initialization allows the extension DLL to export CRuntimeClass objects or resources to the client application.
If you are going to use your extension DLL from one or more regular DLLs, you must export an initialization function that creates a CDynLinkLibrary object. That function must be called from each of the regular DLLs that use the extension DLL. An appropriate place to call this initialization function is in the InitInstance member function of the regular DLL’s CWinApp-derived object before using any of the extension DLL's exported classes or functions.
In the DllMain that AppWizard 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. You should check the return value of AfxInitExtensionModule; if a zero value is returned from AfxInitExtensionModule, return zero from your DllMain function.
If your 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. This function allows MFC to clean up the extension DLL when each process detaches from the extension DLL (which happens when the process exits, or when the DLL is unloaded as a result of a AfxFreeLibrary call). If your extension DLL will be linked implicitly to the application, the call to AfxTermExtensionModule is not necessary.
Applications that explicitly link to extension DLLs must call AfxTermExtensionModule when freeing the DLL. They should also use AfxLoadLibrary and AfxFreeLibrary (instead of the Win32 functions LoadLibrary and FreeLibrary) if the application uses multiple threads. Using AfxLoadLibrary and AfxFreeLibrary ensures that the startup and shutdown code that executes when the extension DLL is loaded and unloaded does not corrupt the global MFC state.
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).
Extension DLLs can take care of multithreading by handling the DLL_THREAD_ATTACH and DLL_THREAD_DETACH cases in the DllMain function. These cases are passed to DllMain when threads attach and detach from the DLL. Calling when a DLL is attaching allows the DLL to maintain thread local storage (TLS) indexes for every thread attached to the DLL.
Note that the header file AFXDLLX.H contains special definitions for structures used in extension DLLs, such as the definition for AFX_EXTENSION_MODULE and CDynLinkLibrary. You should include this header file in your extension DLL.
Note It is important that you neither define nor undefine any of the _AFX_NO_XXX macros in stdafx.h. See the Knowledge Base article "PRB: Problems Occur When Defining _AFX_NO_XXX." You can find Knowledge Base articles on the MSDN Library CD, or at https://www.microsoft.com/kb/.
A sample initialization function that handles multithreading is included in in the Win32 SDK documentation. 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.
The MFC sample demonstrates the use of initialization functions.