C# 不平衡堆栈!

C# 不平衡堆栈!,c#,visual-c++,dll,pinvoke,C#,Visual C++,Dll,Pinvoke,我已经写了一个VC++dll。dll中某个方法的声明如下所示: extern "C" _declspec(dllexport) void startIt(int number) { capture = cvCaptureFromCAM(number); } 我使用p/Invoke在C代码中使用这个dll。本人声明如下: [DllImport("Tracking.dll", EntryPoint = "startIt")] public extern static vo

我已经写了一个VC++dll。dll中某个方法的声明如下所示:

extern "C" _declspec(dllexport)
void startIt(int number)
{
     capture = cvCaptureFromCAM(number);
}
我使用p/Invoke在C代码中使用这个dll。本人声明如下:

[DllImport("Tracking.dll", EntryPoint = "startIt")]
        public extern static void startIt(int number);
我将代码中的函数调用为:

startIt(0);
现在,当遇到这一行时,编译器向我抛出以下错误:

A call to PInvoke function 'UsingTracking!UsingTracking.Form1::startIt' has 
unbalanced the stack. This is likely because the managed PInvoke signature does 
not match the unmanaged target signature. Check that the calling convention 
and parameters of the PInvoke signature match the target unmanaged signature.
我无法理解为什么它会抛出这个错误,因为托管代码和非托管代码中的签名都是相同的。此外,在我的另一台机器中,同样的代码在VisualStudio中完美地运行。因此,这使我认为抛出的错误是错误的引导

请帮忙


谢谢

您的
DllImport
属性中是否缺少
CallingConvention=CallingConvention.Cdecl

调用外部函数时,使用的默认值为。由于您的函数使用约定,因此需要将其声明为:

[DllImport("Tracking.dll", EntryPoint = "startIt",
    CallingConvention = CallingConvention.Cdecl)]
public extern static void startIt(int number);

康斯坦丁和弗雷德里克·哈米迪就如何解决这个问题正确地回答了这个问题。这有助于避免最终的堆栈溢出。我自己也被这咬了好几次。这里真正起作用的是.NET 4为32位x86机器(而非64位)上的调试(非发布)构建启用了托管调试助手,用于检查错误指定的p/invoke调用。此MSDN文章详细介绍了以下内容:。斯蒂芬·克利里(Stephen Cleary)在这篇文章中指出了这一点,这是值得称赞的:

您的一台机器是x86,另一台是x64吗?不,两者都是x86。只有一个运行Win7和其他XPS,谢谢你的工作!然而,我仍然想知道为什么在使用Win7时它没有抛出相同的错误@James,应该是这样的,除非Win7在后台执行特殊的管道操作以切换到正确的调用约定。@James,你在Win7上使用了完全相同的dll还是在那里重新编译了它?@Constatin是的,我在XP上重建了它!
stdcall
cdecl
之间的区别在于
stdcall
调用函数负责从堆栈中删除参数(通常使用
RET x
将ESP移动x)使用
cdecl
是调用方的责任。这是我调试此问题时遇到的问题(在切换到.NET 4之后)<如果未指定此选项,则默认为code>stdcall!在我将旧解决方案从.NET 2切换到.NET 4后,这也为我解决了这个问题)