简体   繁体   English

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

[英]Encountering errors when using C++ interop on old MFC/Win32 application

I have inherited an old MFC/Win32 C++ application who's source code I am not supposed to edit. 我继承了一个旧的MFC / Win32 C ++应用程序,该应用程序的源代码不应该编辑。

This MFC application needs to host an old MFC/Win32 C++ DLL. 此MFC应用程序需要承载一个旧的MFC / Win32 C ++ DLL。 This DLL also tries to make function calls through a Mixed-mode wrapper to a managed C++/CLI DLL. 此DLL还会尝试通过混合模式包装程序对托管C ++ / CLI DLL进行函数调用。 I know it sounds a little confusing, so here's a diagram of what I mean: 我知道这听起来有些混乱,所以这是我的意思的图表:

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)

My problem currently is that when I try to mount an object of the C++/CLR wrapper class let's say WrapperClass WC; 目前我的问题是,当我尝试安装C ++ / CLR包装器类的对象时,我们说WrapperClass WC; , the MFC/Win32 application encounters an "Unhandled exception." ,MFC / Win32应用程序遇到“未处理的异常”。

I have a feeling that I may need to somehow host the CLR in a separate process in order to be able to make the object. 我觉得我可能需要以某种方式在单独的进程中托管CLR,以便能够制作该对象。 Is this the right idea? 这是正确的主意吗? Or am I completely out of whack here? 还是我完全不在这里?

The code compiles time and this only occurs at run-time. 代码会编译时间,这只会在运行时发生。

Any ideas? 有任何想法吗?

Here is an example of the code I am trying to run: 这是我尝试运行的代码示例:

MFC/Win32 DLL 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
}

Mixed-Mode Wrapper Class 混合模式包装器类

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 C ++ / CLI DLL

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

UPDATE: I've managed to coax a real exception out of the program. 更新:我设法哄骗程序中的真正例外。 I am now receiving a System.IO.FileNotFound exception with additional information stating: 我现在收到一个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.

Does this mean anything? 这意味着什么吗? I understand that it apparently cannot find CPPCLIProject (Note: this is not the wrapper project), but then if I'm linking on the .lib file from the Mixed-mode wrapper, how would I not receive linker errors then? 我知道它显然找不到CPPCLIProject(注意:这不是包装器项目),但是如果我从混合模式包装器链接到.lib文件,那我怎么不接收链接器错误呢?

Are you sure that the implementation of WrapperClass::FunctionToCall() isn't throwing the exception? 您确定WrapperClass::FunctionToCall()的实现没有WrapperClass::FunctionToCall()异常吗? It looks like you're caching the memory location of a CLR object, and then trying to call one of its members. 似乎您正在缓存CLR对象的内存位置,然后尝试调用其成员之一。 I think the CLR is free to move objects around, so it's possible that you're trying to use an object that has moved. 我认为CLR可以随意移动对象,因此您可能试图使用已移动的对象。

If you change the implementation of WrapperClass::FunctionToCall() to something simple (ie create a CLR object, call a member function), do you still get the same unhandled exception? 如果将WrapperClass::FunctionToCall()的实现更改为简单的东西(即创建CLR对象,调用成员函数),您是否还会得到相同的未处理异常?

UPDATE : Which class is in CPPCLIProject - CPPCLIClass? 更新 :CPPCLIProject-CPPCLIClass中哪个类? Assuming this project represents the C++/CLI DLL, it sounds like it just can't find the assembly to load it when it needs to call your class. 假设此项目代表C ++ / CLI DLL,听起来它在需要调用您的类时只是找不到要加载的程序集。

Where is this assembly on disk relative to the rest of the application? 相对于应用程序的其余部分,此程序集在磁盘上的哪个位置? If your root EXE is unmanaged (which it sounds like it is, since it is MFC/Win32), then the CLR looks in the EXE's directory and the GAC in order to load assemblies (I don't think it looks in the Path, but I'm not positive on that). 如果您的根EXE是不受管的(听起来像是,因为它是MFC / Win32),那么CLR会在EXE的目录和GAC中查找以便加载程序集(我认为它不在Path中,但我对此并不乐观)。

So if the CPPCLIProject isn't in the same directory as the EXE, that could be your problem. 因此,如果CPPCLIProject与EXE不在同一目录中,则可能是您的问题。

Your best bet is to 最好的选择是

  • run under a debugger (add the additional DLLs with debug information to the debug session) 在调试器下运行(将带有调试信息的其他DLL添加到调试会话中)
  • enable break on all (first-chance) exceptions 在所有(优先机会)异常上启用中断
  • trace/assert all HRESULT codes 跟踪/声明所有HRESULT代码
  • in general try to catch 通常尝试赶上
    • C++ exceptions ( try/catch ...) C ++异常( try/catch ...)
    • Windows Structured Exceptions (IIRC _ try/ _catch, but see MSDN ) Windows结构化异常(IIRC _ try / _catch,但请参见MSDN

The idea is to convert the 'unkown exception' into 'known exception'. 这个想法是将“未知异常”转换为“已知异常”。

Normally speaking there is no need to host the CLR part out of process. 通常来说,不需要将CLR部分托管在进程之外。 This is what a mixed-mode DLL is about. 这就是混合模式DLL的含义。 Then again, if this is legacy code, you might be running into complicated mixes of runtime dependencies that, shall we say, could clash. 再说一次,如果这是遗留代码,您可能会遇到运行时依赖关系的复杂混合,我们可以说它们可能会发生冲突。


Further thoughts: 进一步的想法:

If I understand correctly, you have the option to recompile all sources (just not touch the legacy codebase?). 如果我理解正确,则可以选择重新编译所有源代码(只是不接触旧版代码库?)。 If so, make sure all code is compiled against the same version (think Service Packs) and type (think Static vs Dynamic/Multithread/Debug) of the runtime libraries. 如果是这样,请确保所有代码都是针对运行时库的相同版本(请考虑Service Pack)和类型(请考虑静态与动态/动态/多线程/调试)进行编译的。

While you are checking additional pathways, keep an eye on potentially conflicting dependencies on 在检查其他途径时,请注意对以下方面的潜在冲突

  • ATL server libs ATL服务器库
  • MFC libs (again static vs dynamic/Multithread/Debug flavours). MFC库(还是静态还是动态/多线程/调试风格)。

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

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