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