C# 无法在未损坏的 C++ 库上找到入口点

Posted

技术标签:

【中文标题】C# 无法在未损坏的 C++ 库上找到入口点【英文标题】:C# Unable to find entry point on unmangled C++ library 【发布时间】:2014-06-25 21:51:47 【问题描述】:

我收到了错误 “无法在 DLL 'example.dll' 中找到名为 'foo' 的入口点”。

我使用过depends.exe 和DUMPBIN.exe。该函数在那里,并且它的名称未被破坏。

你能看出这有什么特别不对劲的地方吗?

这是 C++ 代码。

//example.cpp
//Using Multibyte Char Set. (if that matters)
//Edit: I can not change this code.
extern "C" _declspec(dllexport) int foo(const char *name)

...

这是 C# 代码。

//importing.cs
public static class ImportClass

[DllImport("example.dll")]
public static extern int foo(string name)

我无法修改 C++,它是由禁止它的外部来源提供的。 提前致谢。

【问题讨论】:

将规范从 _declspec 更改为 __stdcall 我忘了说。我无法更改任何 C++ 代码。它是从禁止篡改的外部来源提供给我的。 那你什么也做不了,问题出在dll上。 伙计.. 太糟糕了。我是否可以创建一个 C++ 包装器来从 dll 调用函数,然后在包装器中使用 _stdcall? 如果您找不到使用 DLLImport 的解决方案,您绝对可以使用所需的调用约定将 C++ 包装在您自己的 C++ 代码中。 【参考方案1】:

您可能在这里成为Name Mangling 的受害者。 Wikipedia Name Mangling

首先使用dumpbin.exe 列出您的dll 导出的定义。

eg: `dumpbin.exe /EXPORTS example.dll`

验证导出的函数的名称。

接下来像这样使用 DLL 导入:

[DllImport("example.dll", EntryPoint = @"TheNameFrom DumpBin goes here")]

您可能还想查找CallingConvention 属性。

【讨论】:

他的 c++ 代码说 extern "C"(禁用 c++ 名称修改) 是的,大多数文档都这么说,但我在实践中看到编译器通常会在函数名称前加上一些东西。例如:underscore,或者通过更改名称的大小写来稍微修改它们。通常最好使用dumpbin 验证入口点错误。 甚至 Dumpbin.exe 也显示它们未损坏。我将使用包装技术并报告结果。【参考方案2】:

根据MSDN,通过DLL Import 导入的方法的默认调用约定是__stdcall,这意味着它将无法找到您的__declspec 方法。尝试将其更改为__stdcall让您的DLLImport 指定CallingConvention.Cdecl

如上所述,名称修改也可能是一个问题,假设您调用的库没有使用 EXPORTS 语句声明方法。

【讨论】:

【参考方案3】:

不要使用重复的文件名。

我的程序加载了错误的“example.dll”;一个没有 foo() 的。

真的很抱歉给大家添麻烦了。

【讨论】:

以上是关于C# 无法在未损坏的 C++ 库上找到入口点的主要内容,如果未能解决你的问题,请参考以下文章

SWIG c++ 到 C# 错误无法找到入口点 SWIGRegisterExceptionCallbacks_xxxx

无法在 DLL 中找到入口点

无法找到入口点 (cpp)

System.EntryNotFoundException:无法在 DLL 中找到入口点

C#调用C DLL笔记,提示:无法在 DLL“xxx.dll”中找到名为“xxxx”的入口点

C#调用C DLL笔记,提示:无法在 DLL“xxx.dll”中找到名为“xxxx”的入口点