开发者

Problems consuming unmanaged dll AET60

开发者 https://www.devze.com 2023-01-22 16:04 出处:网络
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 functio

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消