我有一个来自第三方的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#时遇到错误。但是究竟......?
首先确保实际导出该函数:
在Visual Studio命令提示符中,使用dumpbin /exports whatever.dll
C#不支持C ++名称修改,你需要声明C ++函数
extern "C" {...}
(如果他们来自第三方,可能不是一个选项),或者如果你可以让它工作,可以直接调用受损的名字。让第三方提供功能的非破坏接口可能更容易。
解决了 - 至少到程序没有破坏的程度,实际上给我一个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);
之后我得到了一些其他错误,但“无法找到切入点”消失了。
我用C ++ / CLI编写了一个包装器。此包装器将能够包含.h文件并链接到您从第三方供应商处获得的.lib文件。然后,为C#程序编写托管接口既简单又安全。
我在这些步骤中解决了同样的问题:
步骤1)如果使用Visual Studio在C ++中编写自定义DLL,则在项目的属性页面中将Common Language Runtime Support (/clr)
parameter设置为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);
在DllImport中指定CallingConvention时,您可以尝试使用未编码的名称
可以在“.lib”文件中找到正确的EntryPoint字符串,该文件随主要的非托管dll一起提供。