“无法在 dll 中找到名为 [function] 的入口点”(c++ 到 c# 类型转换)
Posted
技术标签:
【中文标题】“无法在 dll 中找到名为 [function] 的入口点”(c++ 到 c# 类型转换)【英文标题】:"Unable to find an entry point named [function] in dll" (c++ to c# type conversion) 【发布时间】:2010-10-13 18:46:56 【问题描述】:我有一个来自第三方的 dll,它是用 C++ 编写的。 以下是来自 dll 文档的一些信息:
//start documentation
RECO_DATA
wchar_t Surname[200];
wchar_t Firstname[200];
说明: 接收函数结果的数据结构。所有函数结果将是 存储为 Unicode (UTF-8)。
方法:
bool recoCHN_P_Name(char *imgPath,RECO_DATA *o_data);
输入:
char * imgPath
此图像位置的完整路径 识别功能
RECO_DATA * o_data
接收函数的数据对象 结果。 函数返回: 成功则返回 true,否则返回 false。
//end documentation
我正在尝试从我的 C# 应用程序中调用 recoCHN_P_Name。为此,我想出了这段代码:
导入dll的代码:
public class cnOCRsdk
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct RECO_DATA
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=200)]
public string FirstName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)]
public string Surname;
[DllImport(@"cnOCRsdk.dll", EntryPoint="recoCHN_P_Name")]
public static extern bool recoCHN_P_Name(byte[] imgPath, RECO_DATA o_data);
调用函数的代码:
cnOCRsdk.RECO_DATA recoData = new cnOCRsdk.RECO_DATA();
string path = @"C:\WINDOWS\twain_32\twainrgb.bmp";
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] bytes = encoding.GetBytes(path);
bool res = cnOCRsdk.recoCHN_P_Name(bytes, recoData);
我得到的错误是 ""在 DLL 'cnOCRsdk.dll' 中找不到名为 'recoCHN_P_Name' 的入口点。" 我怀疑我在将类型从 C++ 转换为 C# 时出错。但具体在哪里……?
【问题讨论】:
【参考方案1】:首先确定函数是否被实际导出:
在 Visual Studio 命令提示符中,使用 dumpbin /exports whatever.dll
【讨论】:
我在输出中有一行写着“14 D 00007B40 ?recoCHN_P_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z”这告诉我什么? 查看kegel.com/mangle.html了解如何解密的详细说明。确保数据类型正确。【参考方案2】:C# 不支持 C++ 名称修改,您需要使用声明 C++ 函数
extern "C" ...
(如果他们来自第三方,则可能不是一个选项),或者如果您可以使其正常工作,则直接调用损坏的名称。让第三方为功能提供未损坏的接口可能更容易。
【讨论】:
【参考方案3】:我会使用 C++/CLI 编写一个包装器。此包装器将能够包含 .h 文件并链接到您从第三方供应商处获得的 .lib 文件。那么为您的 C# 程序编写托管接口既简单又安全。
【讨论】:
【参考方案4】:已解决 - 至少到程序不会中断并实际返回一个 bool 值的程度。
我猜,关键是将入口点指定为“损坏的”名称
[DllImport(@"cnOCRsdk.dll", EntryPoint="?recoCHN_P_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z")]
public static extern bool recoCHN_P_Name(ref string imgPath, ref RECO_DATA o_data);
之后我遇到了一些其他错误,但“无法找到入口点”消失了。
【讨论】:
这会起作用,但如果函数(签名)发生任何变化,您必须更改损坏的名称。建议如上所述在 DLL 中使用extern "C"
定义它们。
@Goku,您可以使用名为 PE Explorer (heaventools.com/overview.htm) 的程序或 Visual Studio 附带的名为 dumpbin.exe
的程序找到它。【参考方案5】:
您可以尝试在 DllImport 中指定 CallingConvention 时使用未损坏的名称
【讨论】:
【参考方案6】:正确的EntryPoint字符串可以在主非托管dll附带的“.lib”文件中找到。
【讨论】:
【参考方案7】:我在这些步骤中解决了同样的问题:步骤 1) 如果您使用 Visual Studio 在 C++ 中编写自定义 DLL,则在项目的属性页中设置Common Language Runtime Support (/clr)
参数到Common Language Runtime Support (/clr)
。 步骤 2) 要在 .h
文件中使用 __declspec(dllexport)
关键字,如下所示:
__declspec(dllexport) double Sum(int a,int b);
步骤 3) 构建并导出 DLL 文件,然后使用 Dependency Walker 软件获取您的函数 EntryPoint。 step4) 导入 DLL 文件在 C# 项目中,设置 EntryPoint 和 CallingConvention 变量如下:
[DllImport("custom.dll", EntryPoint = "?Sum@@YAXHHHHHHNNN@Z", CallingConvention = CallingConvention.Cdecl)]
public static extern double Sum(int a,int b);
【讨论】:
__declspec(dllexport)
对我来说很关键,another answer 有人用extern "C"
标记他们,但没有任何内容被导出,谢谢!
谢谢!我见过大约 10 种推荐使用“extern C”和“__declspec(dllexport)”的解决方案。 C++ 编译器不能与 extern 一起使用,但我无法找出原因。这对我来说是第一次。【参考方案8】:
当我们想要访问数据库时遇到了这个问题,并通过将 EF 核心更改为 EF 6.4.4 来解决它 可能是您遇到了这样的问题,需要更改或降级您的 EF 版本(如果您使用过 EF)
【讨论】:
【参考方案9】:我们遇到了这个问题。我们将 EntityFramework.core 更改为 EntityFrameWork 6.4.4,之后程序运行良好。你最改变的是框架版本。
【讨论】:
以上是关于“无法在 dll 中找到名为 [function] 的入口点”(c++ 到 c# 类型转换)的主要内容,如果未能解决你的问题,请参考以下文章