我已经构建了一个MFC项目(可执行文件)作为dll或更准确我已经添加了导出函数就像一个DLL.我可以加载并执行导出的函数,但问题是当我加载模块时,主应用程序类CMyApp theApp
不会被实例化.这意味着我无法使用theApp
我真正想要的对象.我甚至修改了下面的函数,所以它匹配标准MFC dll的函数.
BOOL CMyApp::InitInstance() { CWinApp::InitInstance(); return TRUE; }
我LoadLibrary()
用来加载exe/dll.注意,我不是从dll导出任何c ++类,只是几个标准的C风格函数.这些函数内部想要使用主应用程序对象,但它没有实例化(从不调用它的构造函数).我需要做什么才能正确实例化app类,就像在标准的mfc dll中一样?
**更新**
理想情况下,我想在exe本身中提供导出的函数,我已经完成了,但是当我使用LoadLibrary
应用程序theApp
类加载它时,不会实例化.我相信这是相同的行为,即使它是一个DLL.我的项目有很多依赖项,并创建一个新的DLL项目,添加所有文件和库太麻烦了.我真的想改变当前项目的项目设置,如果有的话,我可以加载正确实例化的应用程序类,就像常规的MFC dll一样.但问题是我需要改变哪些项目设置?
注意:我将使用实例化主对话框对象#define
.基本上dll版本的InitInstance()
函数可以像我上面发布的那样简单.
您描述的是动态链接到MFC的常规DLL.从此链接文章中选择部分描述会为您提供特征的子集:
动态链接到MFC的常规DLL具有以下要求:
这些DLL使用_AFXDLL进行编译,就像动态链接到MFC DLL的可执行文件一样.但_USRDLL也被定义,就像静态链接到MFC的常规DLL一样.
这种类型的DLL必须实例化CWinApp派生类.
这种类型的DLL使用MFC提供的DllMain.将所有特定于DLL的初始化代码放在ExitInstance中的InitInstance成员函数和终止代码中,就像在普通的MFC应用程序中一样.
如果你使用VS2010的New Project Wizatd并选择创建MFC DLL的选项,这是你得到的默认值,尽管你可以从向导选项中选择其他类型的DLL:
因此,创建一个常规的DLL.它将为您生成必要的样板代码,包括CWinApp
派生类.例如:
// CMFCLibrary1App BEGIN_MESSAGE_MAP(CMFCLibrary1App, CWinApp) END_MESSAGE_MAP() // CMFCLibrary1App construction CMFCLibrary1App::CMFCLibrary1App() { // TODO: add construction code here, // Place all significant initialization in InitInstance } // The one and only CMFCLibrary1App object CMFCLibrary1App theApp; // CMFCLibrary1App initialization BOOL CMFCLibrary1App::InitInstance() { CWinApp::InitInstance(); return TRUE; }
我建议您创建这样一个项目,然后将现有代码移植到其中,然后您将从一开始就拥有所有正确的项目设置和结构.这比尝试将exe项目转换为dll项目容易得多.
请务必注意必须编写导出函数的方式的不同之处.如上面的链接所示:
因为这种DLL使用MFC的动态链接库版本,所以必须将当前模块状态显式设置为DLL的状态.为此,请
AFX_MANAGE_STATE
在从DLL导出的每个函数的开头使用宏.
因此,即使您只导出C风格的函数,如果它们包装使用MFC的对象,那么导出的函数和导出类的任何公共函数都必须使用上述技术,特别是对于多线程应用程序.
New Project模板也有助于插入解释这一点的注释:
//TODO: If this DLL is dynamically linked against the MFC DLLs, // any functions exported from this DLL which call into // MFC must have the AFX_MANAGE_STATE macro added at the // very beginning of the function. // // For example: // // extern "C" BOOL PASCAL EXPORT ExportedFunction() // { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // normal function body here // } // // It is very important that this macro appear in each // function, prior to any calls into MFC. This means that // it must appear as the first statement within the // function, even before any object variable declarations // as their constructors may generate calls into the MFC // DLL. // // Please see MFC Technical Notes 33 and 58 for additional // details. //
上述评论中提到的技术说明如下:
TN033:MFC和的 DLL版本
TN058:MFC模块状态实现
看到你LoadLibrary
用来动态加载你的DLL,如果你是从MFC应用程序这样做,你应该明智地使用AfxLoadLibrary
(和相应的AfxFreeLibrary
).正如MSDN所说:
对于加载扩展DLL的MFC应用程序,我们建议您使用AfxLoadLibrary而不是LoadLibrary.在调用LoadLibrary之前,AfxLoadLibrary处理线程同步.AfxLoadLibrary的接口(函数原型)与LoadLibrary相同.
该文档AfxLoadLibrary
有更多详细信息.