我已经构建了一个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
取出主对话框对象的实例化。基本上,InitInstance()
函数的dll版本可以像上面发布的那样简单。
答案 0 :(得分:6)
您描述的是Regular DLL Dynamically Linked to MFC。从此链接文章中选择部分描述会为您提供特征的子集:
动态链接到MFC的常规DLL具有以下内容 要求:
这些DLL是使用_AFXDLL定义编译的,就像动态链接到MFC DLL的可执行文件一样。但_USRDLL是 也定义了,就像静态链接的常规DLL一样 MFC
此类型的DLL必须实例化CWinApp派生类。
这种类型的DLL使用MFC提供的DllMain。将所有特定于DLL的初始化代码放在InitInstance成员函数中 与正常MFC应用程序中的ExitInstance中的终止代码一样。
如果你使用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;
}
我建议您创建这样一个项目,然后将现有代码移植到其中,然后您将从一开始就拥有所有正确的项目设置和结构。这比尝试转换例如要容易得多。一个dll项目的exe项目。
请务必注意必须编写导出函数的方式的不同之处。如上面的链接所示:
因为这种DLL使用MFC的动态链接库版本, 您必须将当前模块状态显式设置为 DLL。为此,请使用开头的
AFX_MANAGE_STATE
宏 从DLL导出的每个函数。
因此,即使您只导出C风格的函数,如果它们包装使用MFC的对象,那么导出的函数和导出类的任何公共函数都必须使用上述技术,特别是对于多线程应用程序。
新项目模板有助于插入解释此问题的评论:
//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.
//
上述评论中提到的技术说明是:
看到您使用LoadLibrary
动态加载DLL,如果您是从MFC应用程序执行此操作,则最好使用AfxLoadLibrary
(以及相应的AfxFreeLibrary
) 。正如MSDN所说:
对于加载扩展DLL的MFC应用程序,我们建议您 使用 AfxLoadLibrary 而不是 LoadLibrary 。 AfxLoadLibrary 处理 调用 LoadLibrary 之前的线程同步。界面 (功能原型)到 AfxLoadLibrary 与 LoadLibrary 相同。
答案 1 :(得分:0)
我遇到了同样的问题,我的问题是lpszClassName
为空RegisterClassEx
。请务必使用相同的字符串调用CreateWindow
。
如果您的问题不是这样,请使用GetLastError()
打印实际的错误消息。缺少lpszClassName
导致错误代码1407
。