Подтвердить что ты не робот

Вызов функции PInvoke '[...]' не сбалансировал стек

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

[DllImport(CudaLibDir)] 

To:

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

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

Ответ 3

Также может быть, что в .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)]

Ответ 4

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

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

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

Ответ 5

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

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