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

news/2025/2/22 23:56:12

概要

按照设计,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 中将无效。
示例代码
转:http://www.cnblogs.com/helloboyang/p/5237648.html

//////////////////////////////////////////////////////////////////// 
// 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;
}

http://www.niftyadmin.cn/n/1535450.html

相关文章

Qt从零开始制作串口调试助手-(第七章、设置窗口标题(中文)和图标)-Creator_Ly

第七章、设置窗口标题(中文)和图标 1、设置窗口标题: ㈠、用setWindowTitle函数即可添加英文标题,如下: ⑵、但是当把英文标题直接换成中文时,则会出现乱码,如下: 这是由于不同的编…

如果程序出现Segment fault错误,该如何排错?谈SIGBUS和SIGSEGV

2010年网易有道的一道考基础知识的面试题,如果程序出现Segment fault错误,该如何排错?那么,什么是Segment fault?这里笔者引用一篇文章,说的很清楚。 SIGBUS和SIGSEGV也许是我们在平时遇到的次数最多的两个…

Qt从零开始制作串口调试助手-(第八章、添加串口配置程序)-Creator_Ly

第八章、添加串口配置程序 说明:在Qt中并没有关于串口的控件,现在大部分都是使用第三方写的qextsrialport类。 官方下载地址:http://sourceforge.net/projects/qextserialport/files/ 个人网盘下载地址: 1、创建文件夹E:\Qt_W…

分词:词性标注北大标准

汉语词性对照表[北大标准/中科院标准] 词性编码词性名称注 解 Ag 形语素 形容词性语素。形容词代码为 a,语素代码g前面置以A。 a 形容词 取英语形容词 adjective的第1个字母。 ad 副形词 直接作状语的形容词。形容词代码 a和副词代码d并在一起。…

Atl com 支持MFC没有DLLMian()函数的替代解决办法

在建立atl com接口DLL时,如果加入了Mfc支持,系统就会自动建立DLLMain函数,而且函数的位置特殊,可参见:http://www.cnblogs.com/helloboyang/p/5237648.html, 如果程序需要在DLLMain()函数中实现处理过程怎…

Qt从零开始制作串口调试助手-(第九章、串口读数据实现)-Creator_Ly

第九章、串口读数据实现 说明: 在上一章节的添加的串口数据读取连接语句中,有提到ReadMyCom()为串口读函数,这里将实现串口读函数的内容。 1、在ComDialog.h中添加读取串口数据函数声明 2、在ComDialog.c中添加读取串口数据函数 3、在实现读…

sqlserver 处理百万级以上的数据处理与优化

一处理百万级以上的数据提高查询速度的方法&#xff1a; 1.应尽量避免在 where 子句中使用!或<>操作符&#xff0c;否则将引擎放弃使用索引而进行全表扫描。 2.对查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索…

隐马尔可夫模型及其在分词中的简单应用

隐马尔可夫模型是一个五元组<S,O,A,B,π>&#xff1a; S&#xff1a;状态集合&#xff1a;即所有可能的状态s1,s2,…,sn所组成的集合。 O&#xff1a;观察序列&#xff1a;即实际存在的一个状态的有向序列&#xff0c;如状态o1,o2,…,on&#xff0c;注意状态是存在顺序…