2010-12-08 42 views
6

Référencer How to get IntPtr from byte[] in C#IntPtr à Tableau d'octets et Retour

Je tente de lire les données d'un IntPtr fait référence dans un octet [], puis de nouveau dans un autre IntPtr. Le pointeur fait référence à une image capturée à partir d'un périphérique de scanner. J'ai donc supposé que la capture de cette information devrait être placée dans un tableau d'octets.

Je ne suis pas sûr non plus si la méthode Marshal.SizeOf() retournera la taille des données référencées par IntPtr ou la taille du pointeur lui-même.

Mon problème est que je reçois l'erreur « Type « System.Byte [] » ne peut pas être marshalés comme une structure non gérée, pas de taille significative ou OFFSET peut être calculée »

IntPtr bmpptr = Twain.GlobalLock (hImage); 

try 
{ 
    byte[] _imageTemp = new byte[Marshal.SizeOf(bmpptr)]; 
    Marshal.Copy(bmpptr, _imageTemp, 0, Marshal.SizeOf(bmpptr)); 

    IntPtr unmanagedPointer = Marshal.AllocHGlobal(
     Marshal.SizeOf(_imageTemp)); 

    try 
    { 
      Marshal.Copy(_imageTemp, 0, unmanagedPointer, 
       Marshal.SizeOf(_imageTemp)); 

      Gdip.SaveDIBAs(
       string.Format("{0}\\{1}.{2}", CaptureFolder, "Test", "jpg"), 
       unmanagedPointer, false); 
    } 
    finally 
    { 
      Marshal.FreeHGlobal(unmanagedPointer); 
    } 
} 
catch (Exception e) 
{ 
     Scanner.control.Test = e.Message; 
} 
+0

Pourquoi ne pouvez-vous pas simplement utiliser 'bmpptr' dans l'appel de' Gdip.SaveDIBAs'? – SwDevMan81

+0

C'est ce que fait le code que je modifie aujourd'hui, ce contrôle est utilisé comme contrôle x actif et nous essayons de nous débarrasser du stockage côté client des images. Gdip.SaveDIBAs enregistre l'image sur le stockage local, je veux être en mesure d'envoyer l'octet [] au serveur pour la création d'image. Ce code est ma tentative de prototype de cette fonctionnalité. –

+0

Ok, donc vous voulez juste passer du non-géré 'bmpptr' à un' byte [] '? – SwDevMan81

Répondre

6

L'exception lancée par l'appel à SizeOf est correcte; la méthode n'a aucun moyen de savoir quelle est la longueur du tableau que vous lui transmettez, elle a juste un pointeur. Pour cela, le moyen le plus simple d'obtenir les données est d'appeler le Copy method on the Marshal class statique, en passant le pointeur sur les données non managées, l'index et le nombre d'octets à lire, ainsi qu'un tampon pré-alloué d'octets à marshal les données dans.

Comme pour obtenir la taille du tableau, comme Anton Tykhyy pointed out in the comments, il semble (être très prudent ici) que l'appel à Twain.GlobalLock(hImage) est en utilisant la mémoire allouée par GlobalAlloc, ce qui signifie que vous pouvez faire un appel à la GlobalSize API function par le calque P/Invoke pour obtenir la taille.

Si elle est pas une poignée à quelque chose allouée par un appel à GlobalAlloc alors vous devez savoir comment le module Twain alloue la mémoire et utiliser le mécanisme approprié pour déterminer la longueur de la mémoire pointée par la IntPtr.

+0

@Scruffy: vous devez obtenir la longueur du tableau par d'autres moyens; essayez 'GlobalSize' (http://msdn.microsoft.com/en-us/library/aa366593.aspx) –

+0

Merci pour votre aide, j'ai utilisé ce document MSDN comme référence pour commencer. Bien que je ne sache toujours pas combien allouer à la taille de l'octet [] de l'IntPtr. –

+0

@Scruffy: Mise à jour de la réponse pour trouver comment (éventuellement) trouver la longueur. – casperOne

2

1- Je suppose bmpptr est déjà un pointeur non géré, si oui, pourquoi avez-vous besoin de 'aller-retour' ce retour à un pointeur non géré unmanagedPointer?

2- Marshal.SizeOf ne vous donnera pas la taille de l'allocation de mémoire non gérée. En utilisant Marshal.Copy, vous pouvez copier le contenu de la mémoire non gérée dans un tableau d'octets géré, mais vous devez savoir combien d'octets doivent être déplacés du tampon non géré vers le tampon géré. L'API devrait idéalement fournir cette information.

+0

Les commentaires ci-dessus, je vais envoyer le tableau d'octets sur le serveur du client, puis en créant les images au lieu d'utiliser le stockage client. –

+0

@Scruffy, alors la même approche devrait s'appliquer. Votre problème consiste à déterminer la taille du tampon. Marshal.SizeOf ne va pas fonctionner, vous devez obtenir cette information de l'API Twain. –