C#无法在未混淆的C++库中找到入口点

3

我遇到了一个错误:"无法在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++代码,因为它是由外部来源提供的,并且被禁止修改。 谢谢您的理解。


我忘了提到。我不能更改任何C++代码。它是从一个禁止篡改的外部来源给我的。 - generic
那你什么都做不了,问题出在dll中。 - Gusman
declspec 用于从动态链接库 (DLL) 导出函数。它不是调用约定。如果没有另外指定,调用约定可能是 _stdcall。 - Beed
如果 DLL 的调用约定不是 _stdcall,您可以尝试在 DLLImport 中指定调用约定属性。 - Beed
1
如果使用DLLImport找不到解决方案,你可以将C++包装在自己的C++代码中,并使用所需的调用约定。 - Jeff Dunlop
显示剩余2条评论
3个回答

2
你可能在这里成为了 Name Mangling 的受害者。 维基百科对于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++名称修饰)。 - Tom
是的,大多数文档都这么说,但实际上我发现编译器通常会在函数名前缀加上一些东西。例如:下划线或稍微修改名称的大小写。最好使用“dumpbin”验证入口点错误。 - Sourav 'Abhi' Mitra
即使Dumpbin.exe显示它们未被混淆,我也将使用包装技术并反馈结果。 - generic

1
根据MSDN,通过DLL导入导入的方法的默认调用约定是__stdcall,这意味着它将无法找到您的__declspec方法。尝试使您的DLLImport指定CallingConvention.Cdecl,或者如果库没有使用EXPORTS语句声明该方法,则名称混淆也可能是一个问题。

1
不要使用重复的文件名。
我的程序加载了错误的“example.dll”,其中没有foo()。
对于所有的麻烦,我真的很抱歉。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接