«Вызов функции PInvoke разбалансирует стек» - PullRequest
7 голосов
/ 25 марта 2012

Я создал приложение Form в 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);
}

Ответы [ 4 ]

14 голосов
/ 25 марта 2012

Ваше объявление Win32 API неверно: «long» отображается на Int64 в .NET Framework, что почти всегда неверно для вызовов Windows API.

Замена long на int должна работать:

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

Для дальнейшего использования вы можете проверить pinvoke.net всякий раз, когда вы 'мы ищем правильный способ вызова функций API - хотя он и не идеален, он показал бы правильное объявление для mouse_event .

(РЕДАКТИРОВАТЬ, 26 марта 2012 г.): И хотя приведенное мной объявление действительно работает, замена long на uint была бы еще лучше, поскольку DWORD в Win32 - это 32-битное целое число без знака .В этом случае вам лучше использовать подписанное целое число (поскольку ни флаги, ни другие аргументы никогда не будут достаточно большими, чтобы вызвать переполнение знака), но это определенно не всегда так.Правильное объявление pinvoke.net, а также следующее:

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

Еще один ответ на этот вопрос уже предоставил правильное объявление, и проблема uint была также отмечена в комментариях.Я отредактировал свой собственный ответ, чтобы сделать это более очевидным;другие участники SO всегда должны свободно редактировать неправильные сообщения, кстати.

5 голосов
/ 25 марта 2012

Вы должны использовать 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 байтов.

4 голосов
/ 25 марта 2012

Попробуйте использовать следующую подпись mouse_event.Примечание uint вместо long .

static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,  int dwExtraInfo);
0 голосов
/ 15 марта 2018

В моем случае:

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

сделал свое дело.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...