24

我有一个来自第三方的 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

用于接收函数结果的数据对象。函数返回:成功则返回真,否则返回假。

//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# 时出错。但是究竟在哪里……?

4

9 回答 9

43

首先确保函数实际被导出:

在 Visual Studio 命令提示符中,使用dumpbin /exports whatever.dll

于 2009-03-17T06:32:49.947 回答
30

C# 不支持 C++ 名称修改,您要么需要声明 C++ 函数

extern "C" {...}

(如果它们来自第三方,则可能不是一个选项),或者如果您可以使其正常工作,则直接调用损坏的名称。让第三方为功能提供未损坏的接口可能更容易。

于 2009-03-17T07:13:44.250 回答
18

解决了 - 至少到程序不会中断并且实际上返回一个布尔值的程度。

我猜,关键是将入口点指定为“损坏的”名称

    [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);

之后我遇到了一些其他错误,但“无法找到入口点”消失了。

于 2009-03-17T23:09:25.037 回答
6

我在这些步骤中解决了同样的问题:

步骤 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)在 C# 项目中导入 DLL 文件并设置EntryPointCallingConvention变量,如下所示:

[DllImport("custom.dll", EntryPoint = "?Sum@@YAXHHHHHHNNN@Z", CallingConvention = CallingConvention.Cdecl)]

    public static extern double Sum(int a,int b);
于 2017-07-21T18:13:50.990 回答
4

我会使用 C++/CLI 编写一个包装器。此包装器将能够包含 .h 文件并链接到您从第三方供应商处获得的 .lib 文件。然后,为您的 C# 程序编写托管接口既简单又安全。

于 2009-03-17T08:08:07.207 回答
2

可以在主非托管 dll 随附的“.lib”文件中找到正确的EntryPoint字符串。

于 2015-09-24T10:12:24.237 回答
0

当我们想要访问 DB 并通过将 EF 核心更改为 EF 6.4.4 来解决这个问题时,我们遇到了这个问题。可能是您遇到了这样的问题,需要更改或降级您的 EF 版本(如果您使用过 EF)

于 2020-06-14T08:10:04.490 回答
0

我们遇到了这个问题。我们将 EntityFramework.core 更改为 EntityFrameWork 6.4.4,之后程序运行良好。你最改变的是框架版本。

于 2020-06-14T08:43:19.817 回答
-1

您可以在 DllImport 中指定 CallingConvention 时尝试使用未损坏的名称

于 2009-03-24T23:00:22.700 回答