PInvokeStackImbalance С# вызов неуправляемой функции С++

После переключения на VS2010 управляемый помощник по отладке отображает ошибку об неуравновешенном стеке от вызова неуправляемой функции С++ из приложения С#.

Обычные подозреваемые, похоже, не вызывают проблемы. Есть что-то еще, что я должен проверить? VS2008 построил С++ dll и С# приложение никогда не было проблемы, никаких странных или таинственных ошибок - да, я знаю, это не означает много.

Вот проверенные вещи:

  • Имя dll правильное.
  • Имя точки входа правильное и было проверено с помощью параметра depend.exe - код должен использовать измененное имя, и он это делает.
  • Правило вызова корректно.
  • Размеры и типы кажутся правильными.
  • Набор символов правильный.
  • Кажется, что не возникли проблемы после игнорирования ошибки, и при запуске вне отладчика нет проблемы.

С#:

[DllImport("Correct.dll", EntryPoint = "SuperSpecialOpenFileFunc", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern short SuperSpecialOpenFileFunc(ref SuperSpecialStruct stuff);

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SuperSpecialStruct
{
   public int field1;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string field2;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
   public string field3;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
   public string field4;
   public ushort field5;
   public ushort field6;
   public ushort field7;
   public short field8;
   public short field9;
   public uint field10;
   public short field11;
};

С++:

short SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);

struct SuperSpecialStruct
{
   int               field1;
   char              field2[256];
   char              field3[20];
   char              field4[10];
   unsigned short    field5;
   unsigned short    field6;
   unsigned short    field7;
   short             field8;
   short             field9;
   unsigned int      field10;
   short             field11;
};

Вот ошибка:

Управляемый помощник по отладке "PInvokeStackImbalance" обнаружил проблемы в "Управляемом пути приложения".

Дополнительная информация: вызов Функция PInvoke "SuperSpecialOpenFileFunc" имеет несбалансированный стек. Это, скорее всего, потому что управляемая подпись PInvoke не соответствует неуправляемой цели подпись. Убедитесь, что вызов соглашение и параметры Подпись PInvoke соответствует целевой неуправляемая подпись.

Ответ 1

Как упоминалось в комментарий Dane Rose, вы можете использовать __stdcall в своей функции С++ или объявить CallingConvention = CallingConvention.Cdecl на DllImport.

Это ответ, который решает мою проблему.

Ответ 2

Вы указываете stdcall в С#, но не в С++, несоответствие здесь приведет к тому, что и функция, и вызывающие вызывающие аргументы выходят из стека.

С другой стороны, есть компилятор, который включит stdcall в качестве соглашения о вызове по умолчанию, (-Gz), используя это?

Или попробуйте это на своем С++

short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);

Ответ 3

В объявлении С# структуры, но не в версии на С++, не указывается дополнение. Поскольку вы смешиваете массивы char, которые не все являются кратными четырем и нечетным количеством 2-байтных шорт, компилятор, вероятно, вставляет добавление в структуру и добавляет конец.

Попробуйте обернуть структуру в #pragma pack, чтобы не было заполнения.

#pragma pack(push)
#pragma pack(1)

// The struct

#pragma pack(pop)

Ответ 4

Имела ту же проблему, что и описано, - неуправляемое приложение на С++, которое отлично работало годами. Когда мы обновились до VS2010, мы начали получать сообщения PInvokeStackUnbalanced.

добавление "__stdcall" к сигнатуре С++, как описано выше, заставило проблему уйти.

Ответ 5

Это хорошо. Я обновляю функцию define, как показано ниже:

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]

Хорошо работает.