我的解决方案有一个非托管的C++ DLL,它导出一个函数,以及一个PInvokes这个函数的托管应用程序。为什么在违反调用约定(.NET 3.5)的情况下PInvoke不会崩溃?
我刚刚将.NET 3.5的解决方案转换为.NET 4.0,并得到了这个PInvokeStackImpalance “调用PInvoke函数时出现了不均衡堆栈”异常。事实证明,我打电话__cdecl'ed功能,因为它是__stdcall:
C++部分(被叫):
__declspec(dllexport) double TestFunction(int param1, int param2); // by default is __cdecl
C#的一部分(主叫):
[DllImport("TestLib.dll")] // by default is CallingConvention.StdCall
private static extern double TestFunction(int param1, int param2);
所以,我已经修复了这个错误,但是现在我对.NET 3.5的工作方式感兴趣了吗?当没有人(无论是被调用者还是调用者)清理堆栈时,为什么(多次重复)情况不会导致堆栈溢出或其他一些不良行为,但工作正常? PInvoke中是否有某种支票,就像Raymond Chen在他的article中提到的那样? 同样有趣的是,为什么相反类型的打破约定(使__stdcall被调用像被__cdecl调用一样)完全不起作用,只会导致EntryPointNotFoundException。
是的,我应该更具体一点,我的应用程序运行在Windows上,其中WinApi意味着StdCall。 – 2011-02-18 17:22:08
正如我在我的回答中写道的,它似乎像PInvoking CDecl函数一样,StdCall是'安全的'。这是额外的MDA检查,它们在.NET 4.0中添加,导致应用程序失败。 – 2011-02-18 17:24:56