PinvokeStackImbalance发生了。抛出此异常但我不知道错误是什么?

时间:2015-09-08 05:34:39

标签: c# c++ pinvoke marshalling dllimport

例外:

托管调试助手' PInvokeStackImbalance'检测到D:\ UI_still_in_progress \ user_interface \ bin \ Debug \ WindowsFormsApplication1.vshost.exe'中的问题。

基本上我的应用程序在c ++中有一个后台实时进程,它与微处理器通信。我设置了一个c ++ dll文件,它允许我实时传递来自c ++应用程序和c#UI的数据。

我的问题是我必须创建一个有限状态机,以确保物理设备和c ++应用程序都在做他们应该根据UI中发生的事情。所以我的目标是将表示状态的简单整数从c#传递给c ++。

使用以下实现,实时数据从c ++传递到c#没有问题:

c ++ .h文件摘要:

extern "C" __declspec (dllexport) int grabx();
extern "C" __declspec (dllexport) void setFSMstate(int s);

C ++ .cpp文件摘要:

int grabx()
{
    return x0;
}

void setFSMstate(int s)
{
    state = s;
}

c#c​​lass

public class MyDllMethods {

    [DllImport("dllTESTER.dll")]
    public static extern int grabx();

    [DllImport("dllTESTER.dll")]
    public static extern void setFSMstate(int s);
}

c#方法调用

xx = MyDllMethods.grabx();
MyDllMethods.setFSMstate(2);

grabx()功能正常工作,我可以实时读取设备的x值。当我的UI移动到新屏幕时,我尝试通过将2传递到setFSMstate()来更改每个应用程序中的状态。调用此方法时,抛出异常。

我对P / Invoke很新,所以如果有什么我错过的请帮帮忙。我可能错误地编组了,但我确信类型int在c#和c ++中是相同的?

1 个答案:

答案 0 :(得分:3)

您遇到的问题是调用约定不匹配。调用约定指定如何将参数传递给函数,以及如何将返回值传递回调用者。您的C ++函数使用__cdecl的隐式调用约定声明,但P / Invoke的默认调用约定为__stdcall

要解决此问题,您只需更改P / Invoke配置:

[DllImport("dllTESTER.dll", CallingConvention = CallingConvention.Cdecl)]

(你没有对第一种方法有任何问题的原因是它没有任何参数 - __cdecl__stdcall以不同方式传递参数,但它们都指定了整数返回值存储在EAX寄存器中。)