«Вызов функции PInvoke разбалансирует стек»

Я создал приложение 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);
}
 Massood Khaari06 окт. 2013 г., 09:18
Проверьтеэтот ответ, Должно решить вашу проблему как можно скорееmouse_event написано с использованиемCdecl Соглашение о вызовах.

Ответы на вопрос(4)

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

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

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

Решение Вопроса

«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 было бы еще лучше, как Win32DWORD это 32-битныйнеподписанный целое число. В этом случае вам лучше использовать подписанное целое число (поскольку ни флаги, ни другие аргументы никогда не будут достаточно большими, чтобы вызвать переполнение знака), но это определенно не всегда так. Объявление pinvoke.net правильное, а также следующее:

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

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

 David Heffernan25 мар. 2012 г., 15:03
На самом деле, ваша декларация неверна. СDWORD 32-разрядное целое число без знака Так что в C # вам нужноuint.

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 байтов.

Попробуйте использовать следующиеmouse_event signeture. ЗаписьUINT вместодолго.

static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,  int dwExtraInfo);
 Pmillan24 мар. 2012 г., 21:57
Спасибо! Это работает для меня, как и решение @mdb, но простое int может быть лучше, чем целое число без знака
 David Heffernan25 мар. 2012 г., 15:04
@Pmillan Почему быint быть лучше чемuint? A CDWORD неподписан и поэтому ответ Павла правильный.

Ваш ответ на вопрос