C# &引用;对PInvoke函数的调用导致堆栈不平衡;

C# &引用;对PInvoke函数的调用导致堆栈不平衡;,c#,.net,visual-studio,click,pinvoke,C#,.net,Visual Studio,Click,Pinvoke,我在visual c#中创建了一个表单应用程序,该应用程序使用一个函数生成鼠标单击,但收到以下错误消息: 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 calli

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

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.
我的代码:

[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);
}

尝试使用以下
鼠标事件
符号。注意uint而不是long

static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,  int dwExtraInfo);

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

用int替换long应该可以:

公共静态外部无效鼠标事件(intdwflags、intdx、intdy、intcbuttons、intdwextrainfo)

为了将来的参考,当您在寻找调用API函数的正确方法时,您可能希望检查pinvoke.net——尽管它并不完美,但它会显示正确的方法

(编辑,2012年3月26日):尽管我提供的声明确实有效,但用
uint
替换
long
会更好,因为Win32的
DWORD
是一个32位无符号整数。在本例中,您可以使用带符号整数(因为标志或其他参数都不会大到足以导致符号溢出),但情况肯定并非总是如此。pinvoke.net声明是正确的,如下所示:

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

这个问题的另一个答案已经提供了正确的声明,评论中也指出了
uint
问题。我编辑了自己的答案,以使这一点更加明显;其他SO参与者也应该随时编辑不正确的帖子,顺便说一句。

你必须使用
uint
而不是
long

请注意,在Microsoft C/C++实现中,
long
int
相同,都是32位的(即使在64位平台上也是如此)。所以它们实际上是可以互换的。64位整数是长的。相反,在C#中,
int
映射到
Int32
,而
long
映射到
Int64
。所以它们不能互换

因此,当p/Invoking时,它在堆栈上放置5*64位/8字节=40字节。但是本机函数只使用和清除5*32位/4字节=20字节。

在我的例子中:

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

成功了。

谢谢!它对我来说很有效,就像@mdb的解决方案一样,但简单的int可能比无符号的要好integer@Pmillan为什么
int
uint
好?C
DWORD
是无符号的,因此Pavel的答案是正确的。实际上,您的声明是错误的。C
DWORD
是一个无符号32位整数。所以在C语言中,你需要
uint
。检查。应该可以解决您的问题,因为
鼠标事件
可能是使用
Cdecl
调用约定编写的。