繁体   English   中英

导入DLL的工作原理不同(VS2003至VS2010,多线程至多线程DLL)

[英]Importing DLL's doesn't work the same (VS2003 to VS2010, multithreaded to multithreaded DLL)

在对VC6,VS2003和VS2005进行大量代码更新时,我遇到了一个问题,即VS2010的行为不像VS2003那样。 该应用程序将扫描DLL的目录,并尝试将其一一加载。 这是在这里完成的:

CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName)
{
    ASSERT(szPluginName);
    ASSERT(AfxIsValidString(szPluginName));

    m_csFullpath = szPluginName;
    m_hModule = LoadLibrary(m_csFullpath);
    m_pInterface = (IConfigDllInterface *) NULL;
    pInterface pPtr = pInterface(NULL);

    if (m_hModule != NULL)
    {
        //  If we loaded the DLL get the interface pointer
        pPtr = pInterface(GetProcAddress(m_hModule, "GetInterface"));
    }
    if (pPtr != NULL)
    {
        pPtr(&m_pInterface);
    }
    else
    {
        ::FreeLibrary(m_hModule);
        m_hModule = HMODULE(NULL);
    }
}

所有DLL都显示为正在加载:...'GenConfig.exe':已加载'C:\\ src \\ Debug \\ config \\ GenLogonConfig.dll',已加载符号。 'GenConfig.exe':已加载'C:\\ src \\ Debug \\ config \\ GenReportConfig.dll',已加载符号。 'GenConfig.exe':已加载'C:\\ src \\ Debug \\ config \\ ImportConfig.dll',已加载符号。 ...

每个DLL都有一个相同的GetInterface实现,如下所示:

CConfigDllInterfaceImpl<CParentDlg> gdllObj;

BOOL GetInterface(IConfigDllInterface **ppPtr)
{
    *ppPtr = &gdllObj;

    // Temporary edit to test if gdllObj is set to proper parent.
    CString name;
    name = gdllObj.GetDisplayName();
    // End edit

    return true;
}

带有如下所示的模板:

__declspec(selectany) UINT guiAdvise;

template <class T> class CConfigDllInterfaceImpl : public IConfigDllInterface
{
public:
    CConfigDllInterfaceImpl()
    {
        guiAdvise = RegisterWindowMessage(_T("GenConfig"));
        m_pDlg = NULL;
    }

    virtual LPCTSTR GetDisplayName() const
    {
        static CString csTemp;

        csTemp.LoadString(IDS_DISPLAY_NAME);
        return csTemp;
    }

    //  Can't be virtual because it uses the template T argument
    BOOL            DoModal(HWND hParent)
    {
        ASSERT(IsWindow(hParent));
        if (m_pDlg == (T *) NULL)
        {
            m_pDlg = new T(CWnd::FromHandle(hParent));
            return m_pDlg->Create();
        }
        else if (IsWindow(m_pDlg->GetSafeHwnd()))
        {
            m_pDlg->PostMessage(guiAdvise, eAdviseSwitchViews);
            m_pDlg->SetActiveWindow();
        }
        return TRUE;
    } // SNIP...

我可以知道我的模板未正确注册到其预期的父对象。 GetDisplayName仅返回“”。 我怀疑问题的原因是,我一个月前决定将所有内容从“多线程”更改为“多线程DLL”。 这些都是MFC项目,这似乎是使用_AFXDLL并使所有内容正确编译和链接的最简单,最简单的方法。 我的所有其他项目都可以正常工作,但是我相信由于此DLL的加载方式:

CConfigDllInterfaceImpl gdllObj;

不再像以前那样工作。

因此,问题1:我的怀疑正确吗? 还是我完全脱离了基地? 问题2:如果我的怀疑是正确的,我该如何解决? 此时,不能选择返回多线程。

提前致谢。

我终于有时间回头回答这个问题。 Collin Dauphinee是正确的,因为这是一个资源问题。 我不知道为什么VS2003与VS2010不同,但是解决方案非常简单。

CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName)
{
    ASSERT(szPluginName);
    ASSERT(AfxIsValidString(szPluginName));

    // Save off current Afx resource handle.
    HINSTANCE hCurrentAfx = AfxGetResourceHandle();  // <---  Didn't need to
                                                     // do this before.

    m_csFullpath = szPluginName;
    m_hModule = NULL;
    m_hModule = LoadLibrary(m_csFullpath);
    m_pInterface = (IConfigDllInterface *) NULL;
    pInterface pPtr = pInterface(NULL);

    if (m_hModule != NULL)
    {
        AfxSetResourceHandle(m_hModule);   // <--- here is where the resources
                                           // get properly set.  This is the
                                           // solution to the problem.

        //  If we loaded the DLL get the interface pointer
        pPtr = pInterface(GetProcAddress(m_hModule, "GetInterface"));
    }
    if (pPtr != NULL)
    {
        pPtr(&m_pInterface);
    }
    else
    {
        ::FreeLibrary(m_hModule);
        m_hModule = HMODULE(NULL);
    }

    // Now put Afx back.
    AfxSetResourceHandle(hCurrentAfx);
}

我希望这可以帮助其他人。 我被困了几天。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM