"对PInvoke函数的调用使堆栈失衡"

Pmi*_*lan 7 .net c# pinvoke click visual-studio

我在visual c#中创建了一个Form应用程序,它使用一个函数来生成鼠标单击,但是我收到以下错误消息:

A call to PInvoke function '...Form1::mouse_event' 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.
Run Code Online (Sandbox Code Playgroud)

我的代码:

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);

private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;

...

void GenerateMouseClick(int x, int y)
{
    Cursor.Position = new Point((int)x, (int)y);
    mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)

mdb*_*mdb 14

您的Win32 API声明不正确:"long"映射到.NET Framework中的Int64,对于Windows API调用几乎总是不正确.

用int替换long应该有效:

public static extern void mouse_event(int dwFlags,int dx,int dy,int cButtons,int dwExtraInfo);

为了将来参考,您可能希望在查找调用API函数的正确方法时检查pinvoke.net - 虽然它并不完美,但它会显示mouse_event正确声明.

(编辑,2012年3月26):虽然我的确提供的申报工作,更换longuint就更好了,是Win32的DWORD是一个32位无符号整数.在这种情况下,您将使用有符号整数(因为标志和其他参数都不会大到足以导致符号溢出),但这绝对不是这样.pinvoke.net声明是正确的,如下所示:

public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
Run Code Online (Sandbox Code Playgroud)

这个问题的另一个答案已经提供了这个正确的声明,并且uint在评论中也指出了这个问题.我编辑了自己的答案,使其更加明显; 其他SO参与者也应该随时编辑错误的帖子,BTW.


Dan*_*ose 5

您必须使用uint代替long

请注意,在Microsoft C / C ++实现中,long和相同int,并且都是32位的(即使在64位平台上也是如此)。因此它们实际上是可互换的。一个64位的int是long long。相反,在C#中,int映射到Int32,并且long映射到Int64。因此它们是不可互换的!

因此,发生的情况是,在P / Invoking时,它将5 * 64位/ 8字节= 40字节放在堆栈上。但是本机函数仅使用并清除5 * 32位/ 4字节= 20字节。