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