在旧的MFC / Win32应用程序上使用C ++ interop时遇到错误

时间:2011-11-30 19:35:31

标签: c++ winapi mfc c++-cli clr

我继承了一个旧的MFC / Win32 C ++应用程序,他的源代码我不应该编辑。

此MFC应用程序需要托管旧的MFC / Win32 C ++ DLL。此DLL还尝试通过混合模式包装器对托管C ++ / CLI DLL进行函数调用。我知道这听起来有点混乱,所以这是我的意思的图表:

Old MFC/Win32 Application (NO CLR)

    ---> Hosting old MFC/Win32 DLL (NO CLR)

                 ---> Making function calls to Mixed-Mode wrapper (CLR)

                              ---> Sending function calls to C++/CLI DLL (CLR)

我当前的问题是,当我尝试挂载C ++ / CLR包装类的对象时,让我们说WrapperClass WC;,MFC / Win32应用程序遇到“未处理的异常。”

我感觉我可能需要以某种方式在单独的进程中托管CLR才能够创建对象。这是正确的想法吗?或者我完全不在这里了?

代码编译时间,这只发生在运行时。

有什么想法吗?

以下是我尝试运行的代码示例:

MFC / Win32 DLL

#include "WrapperClass.h"

BOOL Test::bTest() //This function is called elsewhere within MFC/Win32 DLL
{
    DWORD dwTest;

    WrapperClass WC; //Unhandled exception here!

    return WC.FunctionToCall(dwTest); //FunctionToCall is a BOOL
}

混合模式包装类

BOOL WrapperClass::FunctionToCall(DWORD dw)
{
    GCHandle h = GCHandle::FromIntPtr(IntPtr(m_impl)); //m_impl def'd as void *
    CPPCLIClass^ CCC = safe_cast<CPPCLIClass^>(h.Target);

    return (BOOL)CCC->FunctionToCall(dw);
}

C ++ / CLI DLL

bool CPPCLIClass::FunctionToCall(UInt32 ui32)
{
    if (ui32 == 42)
    {
        return true;
    }
}

更新 我已经成功地从程序中哄骗了一个真正的异常。我现在收到一个System.IO.FileNotFound例外,其中包含以下信息:

An unhandled exception of type 'System.IO.FileNotFoundException' occured in 
Unknown Module.

Additional information: Could not load file or assembly 'CPPCLIProject,
Version=1.0.4351.29839, Culture=neutral, PublicKeyToken=null' or one of its 
dependencies. The system cannot find the file specified.

这意味着什么吗?我明白它显然找不到CPPCLIProject(注意:这不是包装器项目),但是如果我从混合模式包装器链接.lib文件,那我怎么不接收链接器错误?

2 个答案:

答案 0 :(得分:2)

你确定WrapperClass::FunctionToCall()的实现没有抛出异常吗?看起来你正在缓存CLR对象的内存位置,然后尝试调用其中一个成员。我认为CLR可以随意移动对象,因此您可能正在尝试使用已移动的对象。

如果将WrapperClass::FunctionToCall()的实现更改为简单的(即创建CLR对象,调用成员函数),那么仍然会得到相同的未处理异常吗?

更新:CPPCLIProject中哪个类 - CPPCLIClass?假设这个项目代表C ++ / CLI DLL,听起来好像它无法在需要调用你的类时找到加载它的程序集。

磁盘上的此程序集相对于应用程序的其余部分在哪里?如果你的根EXE是不受管理的(它听起来像是MFC / Win32),那么CLR会在EXE的目录和GAC中查找以加载程序集(我不认为它在路径中看起来,但我对此并不积极。)

因此,如果CPPCLIProject与EXE不在同一目录中,那可能是您的问题。

答案 1 :(得分:1)

你最好的选择是

  • 在调试器下运行(将带有调试信息的其他DLL添加到调试会话中)
  • 启用所有(第一次机会)例外的中断
  • trace / assert所有HRESULT代码
  • 一般都试图抓住
    • C ++例外(try/catch ...)
    • Windows结构化例外(IIRC _ 尝试/ _catch,但see MSDN

这个想法是将'未知异常'转换为'已知异常'。

通常情况下,没有必要将CLR部分托管在流程之外。这就是混合模式DLL的意义所在。然后,如果这是遗留代码,您可能会遇到运行时依赖项的复杂混合,我们可以说,这可能会发生冲突。


进一步的想法:

如果我理解正确,您可以选择重新编译所有来源(只是不触及旧版代码库?)。如果是这样,请确保所有代码都是针对相同版本(想想Service Pack)编译的,并键入(认为Static vs Dynamic / Multithread / Debug)运行时库。

在检查其他途径时,请注意

上可能存在冲突的依赖关系
  • ATL服务器库
  • MFC库(再次是静态与动态/多线程/调试风格)。