Ответ 1
Может быть, проблема заключается в вызывающем соглашении. Вы уверены, что неуправляемая функция была скомпилирована как stdcall, а не что-то еще (я бы угадал fastcall)?
Я получаю эту странную ошибку в некоторых вещах, которые я использовал довольно долгое время. Это может быть новая вещь в 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 без проблем.
Может быть, проблема заключается в вызывающем соглашении. Вы уверены, что неуправляемая функция была скомпилирована как stdcall, а не что-то еще (я бы угадал fastcall)?
У меня была 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?
Также может быть, что в .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.