Problems consuming unmanaged dll AET60
Well, I'm trying to call functions in the AET60.dll, which contains the API for AET60 BioCARDKey (finger print and smart card reader) with c#; actually, I have succesfully called almost every function, except for those that manipulate the finger print template: capture, match, enroll. I'm sure it's a problem of parameters types, but the problem is that I can't undestand the type of the template paramter, the dll function capture for example, expects a byte pointer (byte*) to save the template, I've tryed with ref, and unsafe code (for using pointers) and it works fine if called from a console app directly (and the dll import in the same class), but the value pointed is simply a byte (0-255), and there I get lost (256 codes are not enough to identify more than 6 biliion people, so I supose that that byte* is actually something similar to c strings: char*, but I don't know how to use that in c#). Another problem is that if this dll function is encapsulated in a method, an AccesViolationException is thrown when trying to use the template data. Here is some code:
public class NativeMethods
{
private static const Int32 DEFAULT_TIMEOUT = 10000;
[DllImport("AET60.dll")]
private static extern UInt32 AET60_Open();
[DllImport("AET60.dll")]
private static extern UInt32 AET60_Close();
[DllImport("AET60.dll")]
private static extern Int32 AET60_GetNumDevices();
[DllImport("AET60.dll")]
private static extern UInt32 AET60_GetDeviceName(Int32 index, StringBuilder name, ref int nameLength);
[DllImport("AET60.dll")]
private static extern UInt32 AET60_GetMessage(int number, StringBuilder message);
[DllImport("AET60.dll")]
private static extern UInt32 AET60_GetLastStatus();
[DllImport("AET60.dll")]
private static extern UInt32 AET60_GetStatus(UInt32 status, StringBuilder message);
[DllImport("AET60.dll")]
private static extern UInt32 AET60_LockReader(Int32 index);
[DllImport("AET60.dll")]
private static extern UInt32 AET60_UnlockReader();
[DllImport("AET60.dll")]
private static extern UInt32 AET60_Capture(ref byte template, ref Int32 templateLength, UInt32 timeOut);
public static void capture(Template template)
{
Byte templateData = template.Data;
Int32 templateLength = template.Length;
Int32 numberOfDevices;
UInt32 errorCode = NativeMethods.AET60_Open(); //for now Im doing nothing with errorCode
numberOfDevices = NativeMethods.AET60_GetNumDevices();
errorCode = NativeMethods.AET60_LockReader(numberOfDevices - 1);
errorCode = NativeMethods.AET60_Capture(ref templateData, ref templateLength, DEFAULT_TIMEOUT);
errorCode = NativeMethods.AET60_UnlockReader();
template.Data = templateData; //here is thrown the exception
template.Length = templateLength; //here is thrown the exception
errorCode = NativeMethods.AET60_Close();
}
}
In this code, the AccesViolationExeption is thrown. Every other dll functions listed work fine except for AET60_Capture.
The Template class is a simple class containing a byte and 开发者_运维知识库a Int32 field.
Thanks for the help!
I've found the solution, and may be it's usefull for someone.
The whole problem was as I had thought, the type of the template, not in the parameter, but in the application. It must be a byte[] (byte array), and the passed paramter (in) must be the first array position, I din't remember fundamentals, an array is actually a pointer to the first element of a sequenced structure in memory, the second parameter (length) holds the array size. Here is the new code:
public static void capture(ref Template template)
{
if (template == null)
{
template = new Template();
}
Int32 templateLength = template.Length;
Byte[] templateData = new Byte[templateLength];
Int32 numberOfDevices;
UInt32 errorCode = FingerPrintReader.AET60_Open();
numberOfDevices = FingerPrintReader.AET60_GetNumDevices();
errorCode = FingerPrintReader.AET60_LockReader(numberOfDevices - 1);
errorCode = FingerPrintReader.AET60_Capture(ref templateData[0], ref templateLength, DEFAULT_TIMEOUT);
errorCode = FingerPrintReader.AET60_UnlockReader();
errorCode = FingerPrintReader.AET60_Close();
Byte[] auxTemplateData = new Byte[templateLength];
for (int i = 0; i < templateLength; i++)
{
auxTemplateData[i] = templateData[i];
}
template.Data = auxTemplateData;
template.Length = templateLength;
}
The final part is just to rezise the array, because the default length is 1024, but the templateData array it's allways smaller.
精彩评论