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
方法。尝试将其更改为让您的DLLImport 指定CallingConvention.Cdecl__stdcall
或
如上所述,名称修改也可能是一个问题,假设您调用的库没有使用 EXPORTS
语句声明方法。
【讨论】:
【参考方案3】:不要使用重复的文件名。
我的程序加载了错误的“example.dll”;一个没有 foo() 的。
真的很抱歉给大家添麻烦了。
【讨论】:
以上是关于C# 无法在未损坏的 C++ 库上找到入口点的主要内容,如果未能解决你的问题,请参考以下文章
SWIG c++ 到 C# 错误无法找到入口点 SWIGRegisterExceptionCallbacks_xxxx
System.EntryNotFoundException:无法在 DLL 中找到入口点