Невозможно вызвать запись импорта DLL, C# -> C++, EntryPointNotFoundException
-
20-09-2019 - |
Вопрос
Я пытаюсь вызвать из С# функцию в специальной DLL, написанной на С++.Однако я получаю предупреждение во время анализа кода и ошибку во время выполнения:
Предупреждение:СА1400:Microsoft.Интероперабельность:Исправьте объявление «safenativemethods.sethook ()», чтобы она правильно указывала на существующую точку входа в «wi.dll».Имя неуправляемой точки входа в настоящее время связано с Sethook.
Ошибка:System.EntryPointNotFoundException была неразрушкой.Невозможно найти точку входа под названием «Sethook» в dll 'wi.dll'.
Оба проекта, wi.dll и C# exe, скомпилированы в одну и ту же папку DEBUG, оба файла находятся здесь.Во всей файловой системе есть только один файл с именем wi.dll.
Определение функции C++ выглядит так:
#define WI_API __declspec(dllexport)
bool WI_API SetHook();
Я вижу экспортированную функцию с помощью Dependency Walker:
as decorated: bool SetHook(void)
as undecorated: ?SetHook@@YA_NXZ
Импорт C# DLL выглядит следующим образом (я определил эти строки с помощью CLRInsideOut из журнала MSDN):
[DllImport("wi.dll", EntryPoint = "SetHook", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.I1)]
internal static extern bool SetHook();
Я также пробовал без определений EntryPoint и CallingConvention.
Оба проекта 32-битные, я использую 64-битную версию W7, VS 2010 RC.
Я думаю, что я просто что-то упустил из виду....
Заранее спасибо.
Решение
Итак, вы знаете имя точки входа, используйте свойство EntryPoint = "?SetHook@@YA_NXZ" в атрибуте [DllImport].Или поместите extern «C» перед объявлением в вашем коде C++, чтобы имя не было искажено.
[DllImport("wi.dll", EntryPoint = "?SetHook@@YA_NXZ", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.I1)]
internal static extern bool SetHook();
Другие советы
CallingConvention.Cdecl
означает C, а не C++, поэтому, если у вас есть функция с декорированным именем C++, вам нужно использовать декорированное имя в качестве вашего EntryPoint
или используйте Extern «C» в объявлении кода C++, чтобы отключить украшение имени C++.