2010-11-01 6 views
1

Eh bien, j'essaie d'appeler des fonctions dans l'AET60.dll, qui contient l'API pour AET60 BioCARDKey (empreinte digitale et lecteur de carte à puce) avec C#; En fait, j'ai appelé avec succès presque toutes les fonctions, à l'exception de celles qui manipulent le modèle d'empreinte digitale: capture, correspondance, inscription. Je suis sûr que c'est un problème de types de paramètres, mais le problème est que je ne peux pas deviner le type de paramètre de modèle, la capture de fonction dll par exemple, attend un octet pointeur (octet *) pour enregistrer le modèle, ai essayé avec ref, et un code dangereux (pour utiliser des pointeurs) et ça marche bien si on l'appelle depuis une application console directement (et l'importation dll dans la même classe), mais la valeur pointée est simplement un octet (0-255), et là je me perds (256 codes ne suffisent pas pour identifier plus de 6 personnes de biliions, donc je suppose que cet octet * est en fait quelque chose de similaire à c: char *, mais je ne sais pas comment l'utiliser en C#) . Un autre problème est que si cette fonction dll est encapsulée dans une méthode, une exception AccesViolationException est lancée lors de la tentative d'utilisation des données du modèle. Voici un code:Problèmes consommant dll non géré AET60

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

}

Dans ce code, le AccesViolationExeption est jeté. Toutes les autres fonctions dll listées fonctionnent correctement sauf pour AET60_Capture.

La classe Template est une classe simple contenant un octet et un champ Int32.

Merci pour l'aide!

Répondre

0

J'ai trouvé la solution, et peut-être que c'est utile pour quelqu'un.

Tout le problème était comme je l'avais pensé, le type du modèle, pas dans le paramètre, mais dans l'application. Il doit être un octet [] (tableau d'octets), et le paramètre passé (in) doit être la première position du tableau, je ne me souviens pas des fondamentaux, un tableau est en fait un pointeur vers le premier élément d'une structure séquencée en mémoire, le second paramètre (longueur) contient la taille du tableau. Voici le nouveau 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; 
    } 

La dernière partie est juste pour le tableau la dimension, parce que la longueur par défaut est 1024, mais le tableau templateData est toujours gavée plus petit.

Questions connexes