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

Я получаю эту странную ошибку в некоторых вещах, которые я использовал довольно долго. Это может быть новая вещь в Visual Studio 2010, но я не уверен.
Я пытаюсь вызвать незафиксированную функцию, написанную на C ++ с C #.
Из того, что я читал в Интернете и самого сообщения об ошибке, это связано с тем, что подпись в моем C #-файле не такая же, как у C ++, но я действительно не могу ее видеть.
Прежде всего, это моя неизмененная функция ниже:

TEngine GCreateEngine(int width,int height,int depth,int deviceType); 

И вот моя функция в C #:

 [DllImport("Engine.dll", EntryPoint = "GCreateEngine", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr CreateEngine(int width,int height,int depth,int device); 

Когда я отлаживаю в C ++, я вижу все аргументы просто прекрасными, поэтому могу только подумать, что он имеет какое-то отношение к преобразованию из TEngine (который является указателем на class с именем CEngine) в IntPtr. Я использовал это раньше в VS2008 без проблем.

Возможно, проблема заключается в вызывающем соглашении. Вы уверены, что неуправляемая функция была скомпилирована как stdcall, а не что-то еще (я бы предположил fastcall)?

У меня была _cdecl c ++ dll, которую я вызывал без каких-либо проблем с Visual Studio 2008, а затем идентичный код в Visual Studio 2010 не работал. Я получил тот же PInvoke … также неравновел ошибку стека.

Решение для меня состояло в том, чтобы указать соглашение о вызове в атрибуте DllImport (…): From:

 [DllImport(CudaLibDir)] 

Для того, чтобы:

 [DllImport(CudaLibDir, CallingConvention = CallingConvention.Cdecl)] 

Я предполагаю, что они изменили соглашение по умолчанию для DLLImport между .NET 3.5 и .NET 4.0?

Также может быть, что в .NET Framework версии 3.5, pInvokeStackImbalance MDA отключен по умолчанию. В версии 4.0 (или, возможно, VS2010) она включена по умолчанию .

Да. Технически код всегда был неправильным, и предыдущие версии структуры молча исправили его.

Чтобы процитировать документ « Проблемы с миграцией .NET Framework 4» : «Чтобы повысить производительность при взаимодействии с неуправляемым кодом, неправильные соглашения о вызовах в вызове платформы теперь приводят к сбою приложения. В предыдущих версиях уровень маршалинга разрешал эти ошибки в стеке. Если у вас есть двоичные файлы, которые не могут быть обновлены, вы можете включить элемент < NetFx40_PInvokeStackResilience > в файл конфигурации вашего приложения, чтобы разрешить ошибки вызова, которые должны быть разрешены в стеке, как в более ранних версиях, но это может повлиять на производительность вашего приложения ».

Легкий способ исправить это – указать соглашение о вызове и убедиться, что он такой же, как в DLL. A __declspec(dllexport) должен давать формат cdecl .

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

Используйте следующий код, если, например, ваша DLL имеет имя MyDLL.dll, и вы хотите использовать функцию MyFunction в Dll

 [DllImport("MyDLL.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] public static extern void MyFunction(); 

это сработало для меня.

В моем случае (VB 2010 и DLL, скомпилированные с Intel Fortran 2011 XE) проблема возникает, когда мое приложение нацелено на .NET Framework 4. Если я изменю целевую структуру до версии 3.5, тогда все будет работать нормально, как ожидалось. Итак, я бы предположил, что причина – это что-то введенное в .Net Framework 4, но я не знаю, в какой момент

Обновление: проблема была решена путем перекомпиляции библиотеки Fortran DLL и явным образом указывала STDCALL как соглашение о вызове для имен экспорта в DLL.

Давайте будем гением компьютера.