Невозможно вызвать запись импорта DLL, C # - ›C ++, EntryPointNotFoundException

Я пытаюсь вызвать из C # функцию в пользовательской DLL, написанной на C ++. Однако я получаю предупреждение во время анализа кода и ошибку во время выполнения:

Предупреждение: CA1400: Microsoft.Interoperability: исправьте объявление 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-битные, я использую W7 64 бит, VS 2010 RC.

Я считаю, что просто что-то упустил ...

Заранее спасибо.


person drumsta    schedule 17.03.2010    source источник


Ответы (2)


Итак, вы знаете имя точки входа, используйте свойство 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();
person Hans Passant    schedule 17.03.2010
comment
Большой! Это помогло, я поставил extern C перед объявлением. Большое спасибо. - person drumsta; 17.03.2010
comment
Поместите __stdcall в объявление, избавит вас от необходимости использовать CallingConvention. - person Hans Passant; 17.03.2010

CallingConvention.Cdecl означает C, а не C ++, поэтому, когда у вас есть функция с декорированным именем C ++, вам нужно использовать декорированное имя в качестве EntryPoint или использовать Extern «C» в объявлении кода C ++, чтобы отключить украшение имени C ++.

person John Knoeller    schedule 17.03.2010