2010-12-08 13 views
6

referencia a How to get IntPtr from byte[] in C#IntPtr de matriz de bytes y Back

Estoy intentando leer los datos que un IntPtr hace referencia en un byte [] y luego de nuevo en otra IntPtr. El puntero hace referencia a una imagen capturada desde un dispositivo de escáner, por lo que también he supuesto que la captura de esta información debe colocarse en una matriz de bytes.

También estoy seguro de si el método Marshal.SizeOf() devolverá el tamaño de los datos que hacen referencia a la IntPtr está o el tamaño del puntero en sí.

Mi problema es que estoy recibiendo el error " 'System.Byte []' no puede ser calculan las referencias como una estructura no administrado; sin cantidad significativa o desplazamiento puede ser calculado"

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

Por qué no puedes simplemente usar 'bmpptr' en la llamada a' Gdip.SaveDIBAs'? – SwDevMan81

+0

eso es lo que el código Estoy modificando está haciendo hoy en día, este control está siendo utilizado como un control Active X y estamos tratando de deshacerse de almacenamiento del lado del cliente de las imágenes. Gdip.SaveDIBAs está guardando la imagen en el almacenamiento local, quiero poder enviar el byte [] al servidor para la creación de la imagen. Este código es mi intento de prototipo de esa funcionalidad. –

+0

Ok, ¿así que solo quieres pasar del 'bmpptr' no gestionado a un' byte [] '? – SwDevMan81

Respuesta

6

La excepción lanzada por la llamada a SizeOf es correcta; el método no tiene forma de saber cuál es la longitud de la matriz que le está pasando, solo tiene un puntero.

Para ello, la forma más fácil de obtener los datos es llamando al Copy method on the Marshal class estático, pasando el puntero a los datos no administrados, el índice y el número de bytes a leer, así como un búfer de bytes previamente asignado a ordenar los datos en.

En cuanto a conseguir el tamaño de la matriz, como Anton Tykhyy pointed out in the comments, que aparece (tener mucho cuidado aquí) que la llamada a Twain.GlobalLock(hImage) es el uso de memoria asignada por GlobalAlloc, lo que significa que se puede hacer una llamada a la GlobalSize API function a través la capa P/Invoke para obtener el tamaño.

Si es no un mango a algo asignados por una llamada a GlobalAlloc entonces usted necesita para averiguar cómo el módulo Twain es la asignación de la memoria y utilizar el mecanismo apropiado para determinar la longitud de la memoria a la que apunta el IntPtr.

+0

@Scruffy: necesita obtener la longitud de la matriz por otros medios; intente 'GlobalSize' (http://msdn.microsoft.com/en-us/library/aa366593.aspx) –

+0

Gracias por su ayuda, utilicé ese documento de MSDN como referencia para comenzar. Aunque aún no tengo claro cuánto asignar al tamaño del byte [] del IntPtr. –

+0

@Scruffy: se actualizó la respuesta para reflejar cómo (posiblemente) encontrar la longitud. – casperOne

2

1- Asumo bmpptr ya es un puntero no administrado, si es así ¿por qué necesita a 'ida y vuelta' esto de nuevo a un puntero no administrado unmanagedPointer?

2- Marshal.SizeOf no le dará el tamaño de la asignación de memoria no administrado.

Usando Marshal.Copy, puede copiar el contenido de la memoria no administrada en una matriz de bytes administrados, pero necesitará saber cuántos bytes deben moverse desde el búfer no administrado al búfer administrado. La API idealmente debería proporcionar esta información.

+0

Los comentarios anteriores, enviaré la matriz de bytes al servidor desde el cliente y luego crearé las imágenes en lugar de usar el almacenamiento del cliente. –

+0

@Scruffy, entonces debería aplicarse el mismo enfoque. Tu problema es determinar el tamaño del buffer. Marshal.SizeOf no va a funcionar, necesitas obtener esa información de la API twain. –

Cuestiones relacionadas