More fun with the scanner. Now we want to get the first name and last name in chinese from the certain types of passports. There is a dll written in C++ which supposedly provides this functionality. The function in this dll takes a path to an image as a parameter and returns a structure that contains first name and last name.
Here is the C++ signature of the function
bool recoCHN_P_Name(char *imgPath,RECO_DATA *o_data);
Here is the RECO_DATA struct
struct RECO_DATA{
wchar_t FirstName[200];
wchar_t Surname[200];
};
Now I have to call the C++ method from my C# code. The 'DllImport' thingy comes to mind. There are heaps of tutorials on that, for example
Call Unmanaged Code. Part 1 - Simple DLLImport
So I quickly come up with the first version:
This is the 'wrapper' class
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);
}
This is the call to the function in the wrapper class
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);
Unfortunately, this gives me a "Unable to find an entry point named 'recoCHN_P_Name' in DLL 'cnOCRsdk.dll'." error. My first guess was that I am converting types from C++ to C# incorrectly. I asked for some help
Unable to find an entry point named [function] in dll
I got a suggestion to use the 'dumpbin' tool
and also a link to the page that explained C++ name mangling
my function had a mangled name of '?recoCHN_P_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z', but how did that help me?
Anyway, I came across another article on calling C++ from C#
Inheriting From a Native C++ Class in C#
and noticed an interesting thing in it:
[DllImport("cppexp.dll", EntryPoint = "?M1@CSimpleClass@@QAEXXZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _M1(__CSimpleClass* ths);
this guy is using the mangled function name as an entry point! Why shouldn't I try this approach?
Long story short, the 'unable to find entry point' error went away and after a few more tweaks I made this work. Unfortunately, the function always returns me false so far, which is probably because all the images I try are 'bad', but at least it does not break anymore.
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@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z")]
public static extern bool recoCHN_P_Name(ref string imgPath, ref RECO_DATA o_data);
}
cnOCRsdk.RECO_DATA recoData = new cnOCRsdk.RECO_DATA();by Evgeny. Also posted on my website
recoData.FirstName = new string(new char[200]);
recoData.Surname = new string(new char[200]);
string path = @"C:\WINDOWS\twain_32\twainrgb.bmp";
bool res = cnOCRsdk.recoCHN_P_Name(ref path, ref recoData);
No comments:
Post a Comment