Проблемы потребления неуправляемой dll AET60 - PullRequest
1 голос
/ 01 ноября 2010

Ну, я пытаюсь вызвать функции в AET60.dll, который содержит API для AET60 BioCARDKey (сканер отпечатков пальцев и смарт-карт) с помощью c #; на самом деле я успешно вызвал почти все функции, кроме тех, которые манипулируют шаблоном отпечатков пальцев: захват, сопоставление, регистрация. Я уверен, что это проблема типов параметров, но проблема в том, что я не могу понять тип параметра шаблона, например, захват функции dll, ожидает байтовый указатель (byte *) для сохранения шаблона, я мы пробовали с ref и небезопасным кодом (для использования указателей), и он прекрасно работает, если вызывается из консольного приложения напрямую (и импорт dll в том же классе), но указанное значение является просто байтом (0-255), и там я заблудился (256 кодов недостаточно для идентификации более 6 человек, поэтому я полагаю, что этот байт * на самом деле похож на строки c: char *, но я не знаю, как использовать это в c #). Другая проблема заключается в том, что если эта dll-функция инкапсулирована в методе, то при попытке использовать данные шаблона выдается исключение AccesViolationException. Вот некоторый код:

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();
    }

}

В этом коде выбрасывается исключение AccesViolationExeption. Все остальные перечисленные функции dll работают нормально, кроме AET60_Capture.

Класс Template представляет собой простой класс, содержащий байт и поле Int32.

Спасибо за помощь!

1 Ответ

0 голосов
/ 03 ноября 2010

Я нашел решение, и, возможно, оно кому-то пригодится.

Вся проблема заключалась в том, как я думал, в типе шаблона не в параметре, а в приложении.Это должен быть byte [] (байтовый массив), и переданный параметр (in) должен быть первой позицией массива, я не помню основ, массив на самом деле является указателем на первый элемент последовательности в памяти,второй параметр (длина) содержит размер массива.Вот новый код:

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;
    }

Последняя часть - просто изменить размер массива, потому что длина по умолчанию - 1024, а массив templateData всегда меньше.

...