MFC应用程序与使用MFC的常规DLL链接时断言失败

时间:2013-06-23 14:24:05

标签: dll mfc assert

我正在将旧的OWL应用程序迁移到MFC。有一个主库有主要的对话框和控件,我开始为旧的OWL编写一个替代类的MFC,如TDialog [继承自CDialogEx],TEdit .....我从OWL添加了所有需要的类,现在我的库成功构建。

我创建了一个新的MFC应用程序[测试库],我从应用程序中使用的dll导出了一个函数[ SowDialogue ],我添加了dl到MFC应用程序的.lib,我调用该函数显示一个简单的对话框,构建成功,但在第一次启动时,应用程序失败并显示以下消息

The assertion failed message

我点击了重试和中断以获得导致断言的那一行

The code where the assertion happened

所以问题在于资源问题。当我与库链接时,MFC无法获得正确的资源模块。

我认为这是因为我使用一个使用MFC的常规dll并共享MFC对象,如果我必须使用MFC扩展库。如何将常规库转换为MFC扩展库。

长期工作后的任何解决方案

修改


这是调用堆栈,这里没有导出的函数,它在应用程序中的所有错误来自dll之前调用任何东西

The call stack when the assertion happened

解决方案


当我将dll转换为MFC扩展库时问题解决了,我真的创建了一个新的mfc扩展dll并且欺骗了它的属性,dll main,stafx包含和预处理器定义

static AFX_EXTENSION_MODULE MFCExtensionDLL = { NULL, NULL };

extern "C" int APIENTRY DllMain( HINSTANCE hInst, DWORD fdwReason, LPVOID)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        TRACE0("MFCExtension.DLL Initializing!\n");

        // Extension DLL one-time initialization
        if (!AfxInitExtensionModule(MFCExtensionDLL, hInst))
            return 0;


        new CDynLinkLibrary(MFCExtensionDLL);

        //My initialization code

        return 1;
    }
    else if (fdwReason == DLL_PROCESS_DETACH)
    {
        // Terminate the library before destructors are called
        AfxTermExtensionModule(MFCExtensionDLL);
        // my finalization code
        return 1;
    }
}

属性

in the properties of project->configuration properties->general Use of MFC = Use MFC in a Shared DLL

in the properties of project->configuration properties->C/C++->Preprocessor->Preprocessor Definitions->add _AFXEXT , make sure to delete _USERDLL if it exists

2 个答案:

答案 0 :(得分:1)

在.dll中使用MFC时,必须确保.dll可以找到.rc文件中字符串和位图等资源句柄。 MFC维护每个.dll的内部状态,指向该.dll的资源。当从应用程序(或另一个.dll)调用该.dll时,你必须'帮助'MFC获得内部状态权限,否则它将无法找到你的资源并且将会ASSERT。

我无法在示例中的调用堆栈中看到函数的正下方,但如果它是导出函数,则MFC状态问题可能正在发生。

确保将AFX_MANAGE_STATE宏放在可从外部访问的任何函数(导出函数)的顶部。这对解决问题大有帮助。

Microsoft参考:http://msdn.microsoft.com/en-us/library/ba9d5yh5(v=vs.80).aspx

答案 1 :(得分:0)

如果您使用dll文件中的资源或Windows,则可以尝试这种方式。此代码可以在dll本身中。每当创建资源时,主进程的当前资源句柄都将被设置为dll的资源句柄并使用该句柄。

在创建任何窗口或更改资源后,将其还原为旧值。

hdllresource = ::LoadLibrary(<dllfile containing the resource>);
hcurrentInst = AfxGetResourceHandle();
AfxSetResourceHandle(hdllresource );

//do your window creation or resource loading stuff 

AfxSetResourceHandle(hdllresource);