【问题标题】:"Unable to find an entry point named [function] in dll" (c++ to c# type conversion)“无法在 dll 中找到名为 [function] 的入口点”(c++ 到 c# 类型转换)
【发布时间】:2023-03-21 13:55:02
【问题描述】:

我有一个来自第三方的 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# 时出错。但具体在哪里……?

【问题讨论】:

    标签: c# c++ dll dllimport extern


    【解决方案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# 项目中,设置 EntryPointCallingConvention 变量如下:

            [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,之后程序运行良好。你最改变的是框架版本。

              【讨论】:

                猜你喜欢
                • 2011-04-14
                • 1970-01-01
                • 1970-01-01
                • 2012-07-06
                • 2015-12-10
                • 1970-01-01
                • 2021-08-05
                • 2017-08-31
                • 1970-01-01
                相关资源
                最近更新 更多