2010-10-15 33 views
1

J'ai cette méthode que j'ai besoin d'appeler et d'utiliser dans mon application, mais je ne sais pas vraiment comment le faire exactement.Appel de code non sécurisé à partir de managed (C#). Reading byte array

C'est la fonction que j'ai besoin d'appeler.

[DllImport(dll_Path)] 
public static extern int DTS_GetDataToBuffer(int Position, int Length, char* Buffer, int* DataRead); 

Dans mon code, j'ai cette fonction et il me manque son implémentation.

internal static void GetDataToBuffer(int position, int length, out byte[] data, out int dataRead) 
    { 
     unsafe 
     { 
      // the code I need 
     } 
    } 

Je pense que la plupart de ceci est très auto-explicatif. J'ai besoin d'implémenter cette dernière fonction pour que je puisse lire les données dans le tampon et la quantité de données lues (ce qui devrait être le même que data.Length, mais le fabricant a ceci comme option séparée, donc j'en ai besoin). Quelqu'un peut-il aider? Est-ce assez clair?

Merci

Edit: Voici la déclaration non géré à partir du fichier .h. J'espère que cela aide.

extern NAG_DLL_EXPIMP int DTS_GetDataToBuffer(int Position, 
           int Length, 
           unsigned char *Buffer, 
           int *DataRead); 

Edit # 2: positons - la position à partir de laquelle étoile la lecture des données. Longueur - La quantité de données à lire (ce serait la taille de la mémoire tampon). DataRead - la taille réelle des données lues.

+0

Pourriez-vous simplement appeler votre fonction à l'intérieur DTS_ méthode GetDataToBuffer? Y a-t-il des problèmes avec cela? –

+0

Je pourrais. Je devrais, mais je ne sais pas comment passer correctement les types gérés à non gérés. C'est tout le problème que j'ai. –

Répondre

7

Je ne pense pas que vous avez vraiment besoin d'utiliser des pointeurs dangereux ici. fonction Declare comme

[DllImport(dll_Path)] 
public static extern int DTS_GetDataToBuffer(
    int  position, 
    int  length, 
    byte[] buffer, 
    ref int dataRead); 

emballage raisonnable C# pour cette fonction:

internal static byte[] GetDataToBuffer() 
{ 
    // set BufferSize to your most common data length 
    const int BufferSize = 1024 * 8; 
    // list of data blocks 
    var chunks = new List<byte[]>(); 
    int dataRead = 1; 
    int position = 0; 
    int totalBytes = 0; 
    while(true) 
    { 
     var chunk = new byte[BufferSize]; 
     // get new block of data 
     DTS_GetDataToBuffer(position, BufferSize, chunk, ref dataRead); 
     position += BufferSize; 
     if(dataRead != 0) 
     { 
      totalBytes += dataRead; 
      // append data block 
      chunks.Add(chunk); 
      if(dataRead < BufferSize) 
      { 
       break; 
      } 
     } 
     else 
     { 
      break; 
     } 
    } 
    switch(chunks.Count) 
    { 
     case 0: // no data blocks read - return empty array 
      return new byte[0]; 
     case 1: // single data block 
      if(totalBytes < BufferSize) 
      { 
       // truncate data block to actual data size 
       var data = new byte[totalBytes]; 
       Array.Copy(chunks[0], data, totalBytes); 
       return data; 
      } 
      else // single data block with size of Exactly BufferSize 
      { 
       return chunks[0]; 
      } 
     default: // multiple data blocks 
      { 
       // construct new array and copy all data blocks to it 
       var data = new byte[totalBytes]; 
       position = 0; 
       for(int i = 0; i < chunks.Count; ++i) 
       { 
        // copy data block 
        Array.Copy(chunks[i], 0, data, position, Math.Min(totalBytes, BufferSize)); 
        position += BufferSize; 
        // we need to handle last data block correctly, 
        // it might be shorted than BufferSize 
        totalBytes -= BufferSize; 
       } 
       return data; 
      } 
    } 
} 
+0

J'ai modifié et ajouté le code du fichier d'en-tête. Le paramètre DataRead est une valeur de retour, il indique les données réelles en cours de lecture. Un peu bizarre, mais c'est une valeur de retour. –

+0

Il n'est pas encore clair comment déterminer la taille du tableau d'entrée (quantité de mémoire à allouer). Si DataRead est uniquement une valeur de retour, DTS_GetDataToBuffer ne peut pas déterminer la taille de la mémoire tampon et un débordement de tampon se produira si le tampon est trop petit. – max

+0

Ajout des paramètres pour Position et Longueur. La longueur est la taille de votre tableau d'octets. J'étais sous impression que la DLL non managée initialiserait la taille du tableau d'octets. Si la déclaration peut être changée, ça me va. Tant que je peux appeler GetDataToBuffer géré de mon code et il appelle la DLL non managée sans erreurs. –

2

Je ne peux pas tester cela, mais je pense que vous devriez laisser la conversion Marshaler-vous (s):

[DllImport(dll_Path)] 
public static extern int DTS_GetDataToBuffer(out byte[] data, out int dataRead);