Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 导入DLL';s不';t工作方式相同(VS2003到VS2010,多线程到多线程DLL)_C++_Templates_Dll - Fatal编程技术网

C++ 导入DLL';s不';t工作方式相同(VS2003到VS2010,多线程到多线程DLL)

C++ 导入DLL';s不';t工作方式相同(VS2003到VS2010,多线程到多线程DLL),c++,templates,dll,C++,Templates,Dll,在混合使用VC6、VS2003和VS2005进行大规模代码更新的过程中,我遇到了一个问题,VS2010的行为与VS2003不同。应用程序将扫描DLL目录,并尝试逐个加载它们。这是在这里完成的: CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName) { ASSERT(szPluginName); ASSERT(AfxIsValidString(szPluginName)); m_csFullpath = szPluginNa

在混合使用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\genlogonfig.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...
cconfigdllinterfaceinpl-gdllObj;
BOOL GetInterface(IConfigDLinInterface**ppPtr)
{
*ppPtr=&gdllObj;
//临时编辑以测试gdllObj是否设置为正确的父级。
CString名称;
name=gdllObj.GetDisplayName();
//结束编辑
返回true;
}
使用如下所示的模板:

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...
\u declspec(selectany)UINT guiadvision;
模板类cconfigdllinterfaceinpl:public IConfigDllInterface
{
公众:
CConfigDllInterfaceImpl()
{
guiadvision=RegisterWindowMessage(_T(“GenConfig”);
m_pDlg=NULL;
}
虚拟LPCTSTR GetDisplayName()常量
{
静态CString-csTemp;
csTemp.LoadString(id\u DISPLAY\u NAME);
返回csTemp;
}
//不能是虚拟的,因为它使用模板t参数
布尔多莫达尔(HWND hParent)
{
断言(IsWindow(hParent));
如果(m_pDlg==(T*)NULL)
{
m_pDlg=newt(CWnd::FromHandle(hParent));
返回m_pDlg->Create();
}
else if(IsWindow(m_pDlg->GetSafeHwnd())
{
m_pDlg->PostMessage(guiadise、eadviseswitchview);
m_pDlg->SetActiveWindow();
}
返回TRUE;
}//剪断。。。
我可以看出我的模板没有正确注册到其预期的父级。GetDisplayName只返回“”我怀疑我的问题的原因是,我在一个月前决定将所有内容从多线程更改为多线程DLL。这些都是MFC项目,使用AFXDLL并使所有内容正确编译和链接似乎是最简单和最简单的方法。我的所有其他项目都工作正常,但我相信,因为f加载此DLL的方式:

CConfigDLinterfaceImpl-gdllObj

不再像以前那样工作了

那么,问题1:我的怀疑是正确的吗?还是我完全错了? 问题2:如果我的怀疑是正确的,我该如何解决这个问题?在这一点上,回到多线程是不可取的


提前感谢。

我终于有时间回答这个问题了。科林·多菲尼说得对,因为这是一个资源问题。我不知道为什么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);
}
CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName)
{
断言(szPluginName);
断言(AfxIsValidString(szPluginName));
//保存当前Afx资源句柄。

HINSTANCE hCurrentAfx=AfxGetResourceHandle();//您是否使用VS2010重建了所有DLL?是的。所有DLL都是同一解决方案的一部分。请确保您的资源不会在更新中丢失。我不太清楚这是什么意思。我可以在DLL中设置断点并查看调试信息。但是如果我在VS2003中设置断点,我可以看到所有句柄都被正确引用。当我设置在VS2010的同一个断点中,这些句柄是空的。我越来越确信关键在于“cconfigdllinterfaceinpl gdllObj。这在加载DLL时运行。但在VS2003中,它按预期设置为父对话框的设置。@CollinDauphinee-你完全正确。尽管我花了四天的时间搜索和重新搜索,最终找到了根本原因。