消耗非托管DLL AET60的问题

时间:2010-11-01 05:27:09

标签: c# .net com-interop

好吧,我正在尝试调用AET60.dll中的函数,其中包含用于AET60 BioCARDKey(指纹和智能卡读卡器)的API和c#;实际上,除了操纵指纹模板的那些功能外,我几乎成功地调用了所有功能:捕获,匹配,注册。 我确定它是参数类型的问题,但问题是我无法解决模板参数的类型,例如dll函数捕获,需要一个字节指针(byte *)来保存模板,我'尝试使用ref和不安全的代码(用于使用指针),如果直接从控制台应用程序调用(并在同一个类中导入dll),它可以正常工作,但指向的值只是一个字节(0-255),并且在那里我迷路了(256个代码不足以识别超过6个biliion人,所以我认为那个字节*实际上类似于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。除了AET60_Capture之外,列出的每个其他dll函数都可以正常工作。

Template类是一个包含byte和Int32字段的简单类。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我找到了解决方案,可能对某人有用。

整个问题就像我原先想到的那样,模板的类型,不在参数中,而是在应用程序中。它必须是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数组总是更小。