簡體   English   中英

“對 PInvoke 函數的調用使堆棧不平衡”

[英]"A call to a PInvoke function has unbalanced the stack"

我在 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.

我的代碼:

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

您的 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 日):雖然我提供的聲明確實有效,但用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++ 實現中, longint相同,並且都是 32 位(即使在 64 位平台上)。 所以它們實際上是可以互換的。 64 位 int 是long long 相比之下,在 C# 中, int映射到Int32long映射到Int64 所以它們不能互換!

那么發生的情況是,當 P/Invoking 時,它會在堆棧上放置 5*64 位/8 字節 = 40 字節。 但是原生函數只使用和清理了 5*32 bits/4 bytes = 20 bytes。

嘗試使用以下mouse_event簽名。 注意uint而不是long

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

就我而言:

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

成功了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM