类没有在dll中实例化

时间:2014-01-10 18:24:36

标签: c++ visual-studio-2010 dll mfc

我已经构建了一个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版本可以像上面发布的那样简单。

2 个答案:

答案 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:

wizard

因此,创建一个常规的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 相同。

documentation for AfxLoadLibrary有更多详情。

答案 1 :(得分:0)

我遇到了同样的问题,我的问题是lpszClassName为空RegisterClassEx。请务必使用相同的字符串调用CreateWindow

如果您的问题不是这样,请使用GetLastError()打印实际的错误消息。缺少lpszClassName导致错误代码1407