PInvokeStackImbalance C# вызов неуправляемой функции C++
После переключения на VS2010, управляемый помощник по отладке отображает ошибку о несбалансированном стеке при вызове неуправляемой функции C++ из приложения C#.
Обычные подозреваемые, кажется, не вызывают проблему. Есть что-то еще, что я должен проверить? Созданные на VS2008 приложения C++ dll и C# никогда не имели проблем, никаких странных или таинственных ошибок - да, я знаю, что это мало что значит.
Вот что было проверено:
- Имя dll правильное.
- Имя точки входа правильное и было проверено с помощью зависящего от.exe файла - код должен использовать искаженное имя, и это так.
- Соглашение о вызовах является правильным.
- Размеры и типы кажутся правильными.
- Набор символов правильный.
- После игнорирования ошибки, похоже, не возникает никаких проблем, и проблема не возникает при запуске вне отладчика.
C#:
[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;
};
C++:
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 соответствуют целевой неуправляемой подписи.
5 ответов
Как упоминалось в комментарии Дейна Роуза, вы можете использовать __stdcall
на вашей функции C++ или объявить CallingConvention = CallingConvention.Cdecl
на ваше DllImport
,
Это ответ, который решает мою проблему.
Вы указываете stdcall в C#, но не в C++, здесь несоответствие приведет к тому, что функция и вызывающий объект вытеснят аргументы из стека.
С другой стороны, есть переключатель компилятора, который включит stdcall как соглашение о вызовах по умолчанию, (-Gz) вы используете это?
Или попробуйте это в вашем C++
short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
Вы не указываете заполнение в своем объявлении C# структуры, но не в версии C++. Так как вы смешиваете массивы символов, которые не являются кратными четырем и нечетным числом 2-байтовых шорт, компилятор, вероятно, вставляет заполнение в структуру и добавляет конец.
Попробуйте обернуть структуру в #pragma pack
чтобы не допустить заполнения.
#pragma pack(push)
#pragma pack(1)
// The struct
#pragma pack(pop)
Возникла та же проблема, что и описанная, - неуправляемое приложение C++, которое отлично работало годами. Когда мы обновились до VS2010, мы начали получать сообщения PInvokeStackUnbalanced.
добавление "__stdcall" к сигнатуре C++, как описано выше, устраняет проблему.
Это хорошо. Функцию обновления я определяю следующим образом:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
Это работает хорошо.