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

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

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 (который является указателем на класс с именем CEngine) в IntPtr. Я использовал это раньше в VS2008 без проблем.

5 ответов


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


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

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

[DllImport(CudaLibDir)] 

в:

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

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


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

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

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

простой способ исправить это-указать соглашение о вызовах и убедиться, что оно такое же, как в DLL. А __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, но я понятия не имею, какой из них

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