如何: 如何提供自己 DllMain MFC 的规则 DLL 中

概要
按照设计,MFC 的规则 Dll 具有 MFC 将自动提供一个默认 DllMain 函数。规则 Dll 不应提供自己 DllMain。应在规则 DLL 中的一个 CWinApp 派生类的 InitInstance 成员函数 DLL 加载时需要的任何初始化。取消初始化和终止代码应放在 ExitInstance 成员函数中。

但是,由 MFC 的 DllMain 进程附加到 DLL (DLL_PROCESS_ATTACH) 和仅当进程与 DLL 分离 (DLL_PROCESS_DETACH) 时,调用 ExitInstance 时才调用 InitInstance。如果有必要处理线程接触和分离 (DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH) 从 MFC 的规则 DLL 中,需要提供其自己 DllMain 规则 DLL。本文介绍了如何执行此操作。
详细信息
创建规则 DLL 时,MFC 源强制链接源文件 \Msdev\Mfc\Src\Dllmodul.cpp 的代码中。Dllmodul.cpp 包含大部分的代码添加到支持该 DLL 中的 MFC 的规则 DLL。在 Dllmodul.cpp 中的最重要功能之一是 DllMain 函数。

将代码添加到 MFC 的 DllMain,将 \Msdev\Mfc\Src\Dllmodul.cpp 文件复制到项目目录中,并包括在项目中复制。这份 Dllmodul.cpp 用于编译和链接到您的 DLL 而不是在 Mfc\Src 目录中,Dllmodul.cpp,所以在 DllMain 更改会显示在最终的 DLL。

主要需要说明的是这并不是推荐的解决方案,并应在绝对必要时才使用。对 Dllmodul.cpp 中的代码的任何更改将肯定会有不可预知的结果。添加代码只、 不要删除或修改现有的代码。

有关在共享库中使用 MFC 的规则 Dll,模块状态应该设置任何添加的代码的开头,并从 DllMain 返回之前恢复。DllMain,处理 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知并正确切换模块状态所需的示例,请参阅本文中的示例代码。

依赖于 DllMain 由于以下情况而被称为 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 时,必须考虑特别加以注意:

  • 在进程中创建线程时,系统会调用 DllMain 值为 DLL_THREAD_ATTACH 每个 Dll 映射到流程中。但是,如果进程有了新的 DLL 映射到它在运行中的多个线程,DllMain 不调用 DLL_THREAD_ATTACH 值与任何现有的线程。
  • 进程的主线程的值 DLL_THREAD_ATTACH,不会调用 DllMain。
  • 线程终止时 (通过调用 ExitThread),在 DllMain 每个 Dll。 DllMain 不称为 DLL_THREAD_DETACH 的任何线程除非线程终止通过调用 ExitThread 与 DLL_THREAD_DETACH 的值调用。
  • 如果线程终止由于对 TerminateThread 的调用,DLL_THREAD_DETACH 的值不调用 DllMain。
  • 有可能一个线程在调用则加载 DLL 与 DLL_PROCESS_ATTACH,导致调用 DllMain,然后在线程终止导致 dllMain 调用 DLL_THREAD_DETACH 而不会调用 DLL_THREAD_ATTACH 的进程中。因此,最佳的线程调用则还调用句是。
注意: MFC CWnd 对象、 CDC 对象、 CMenu 对象、 GDI 对象和 CImageList 对象被限制为每个线程,每个模块的基础。换句话说,在一个模块或线程创建的 MFC 对象不能是传递到或在不同的模块或线程中使用。这有特殊的相关性,因为 DllMain 调用这些原因与不同线程处理 DLL_THREAD_ATTACH 或 DLL_THREAD_DETACH 在 DllMain 中的添加任何代码。在 DLL_THREAD_ATTACH 期间,CWnd 对象,例如,创建在 DllMain 期间 DLL_PROCESS_ATTACH 或 InitInstance 中将无效。

示例代码


//////////////////////////////////////////////////////////////////// 
// export DllMain for the DLL
// Add code in the specified sections only.
// Remove code at your own risk.
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID
/*lpReserved*/)
{
   if (dwReason == DLL_PROCESS_ATTACH)
   {
// ... Code abbreviated from DLLMODUL.CPP
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
// ... Code abbreviated from DLLMODUL.CPP
   }
// NEW CODE ADDED HERE
// -------------------
   else if (dwReason == DLL_THREAD_ATTACH)
   {
#ifdef _AFXDLL
      // set module state
      ASSERT(AfxGetThreadState()->m_pPrevModuleState == NULL);
      AfxGetThreadState()->m_pPrevModuleState =
         AfxSetModuleState(AfxGetStaticModuleState());
#endif
      // ADD DLL_THREAD_ATTACH CODE HERE
      // Remember that this won't necessarily be called for
      // every thread in the process into which this DLL is mapped
      // Threads created by the process BEFORE the DLL
      // was loaded will not call into DLL_THREAD_ATTACH.

#ifdef _AFXDLL
      // restore previously-saved module state
     VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState)
             == AfxGetStaticModuleState());
        DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif

   }
   else if (dwReason ==DLL_THREAD_DETACH)
   {
#ifdef _AFXDLL
      // set module state
      ASSERT(AfxGetThreadState()->m_pPrevModuleState == NULL);
      AfxGetThreadState()->m_pPrevModuleState =
         AfxSetModuleState(AfxGetStaticModuleState());
#endif
      // ADD DLL_THREAD_DETACH CODE HERE

#ifdef _AFXDLL
      // restore previously-saved module state
   VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState)
          == AfxGetStaticModuleState());
      DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif
   }

   return TRUE;
}
				
 

你可能感兴趣的:(如何: 如何提供自己 DllMain MFC 的规则 DLL 中)