【问题标题】:Cannot call DLL import entry, C# -> C++, EntryPointNotFoundException无法调用 DLL 导入条目,C# -> C++,EntryPointNotFoundException
【发布时间】:2011-01-28 17:52:27
【问题描述】:

我正在尝试从 C# 调用用 C++ 编写的自定义 DLL 中的函数。但是我在代码分析期间收到警告,在运行时收到错误:

警告:CA1400: Microsoft.互操作性:正确 的声明 'SafeNativeMethods.SetHook()' 以便 它正确地指向一个现有的 'wi.dll' 中的入口点。不受管理的 当前链接到的入口点名称 是 SetHook。

错误: System.EntryPointNotFoundException 是 未处理。找不到条目 DLL 'wi.dll' 中名为 'SetHook' 的点。

项目 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 导入看起来像(我使用 MSDN 杂志的 CLRInsideOut 定义了这些行):

[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。

我相信我只是忽略了一些东西......

提前致谢。

【问题讨论】:

    标签: winapi pinvoke name-decoration


    【解决方案1】:

    CallingConvention.Cdecl 表示 C 不是 C++,所以当你有一个带有 C++ 修饰名的函数时,你需要使用修饰名作为你的 EntryPoint 或者在 C++ 代码声明中使用 Extern "C" 来关闭 C++名称装饰。

    【讨论】:

      【解决方案2】:

      好吧,您知道入口点名称,请使用 [DllImport] 属性中的 EntryPoint = "?SetHook@@YA_NXZ" 属性。或者将 extern "C" 放在 C++ 代码中的声明之前,这样名称就不会被破坏。

      [DllImport("wi.dll", EntryPoint = "?SetHook@@YA_NXZ", CallingConvention = CallingConvention.Cdecl)]
      [return: MarshalAsAttribute(UnmanagedType.I1)]
      internal static extern bool SetHook();
      

      【讨论】:

      • 太棒了!这有帮助,我在声明之前放了 extern "C"。非常感谢。
      • 将 __stdcall 也放入声明中,让您不必使用 CallingConvention。
      猜你喜欢
      • 2021-04-12
      • 1970-01-01
      • 2016-12-12
      • 2011-04-14
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多