Pregunta

He estado luchando con la Canon EDSDK desde hace un tiempo. Puedo conseguir con éxito la biblioteca para guardar un archivo directamente en el disco, sin embargo, no puedo obtener una bodega de la imagen de bytes [] en la memoria. Siempre que intente Marshal.Copy () la Corriente EDSDK a byte [], siempre me sale el siguiente error:

AccessViolationException: Intento de leer o escribir en la memoria protegida. Esto es a menudo una indicación de que otra memoria está dañada.

A continuación se muestra una de las variantes de código que he utilizado para tratar de obtener la corriente:

        private uint downloadImage(IntPtr directoryItem)
        {
            uint err = EDSDK.EDS_ERR_OK;
            IntPtr stream = IntPtr.Zero;

            // Get information of the directory item.
            EDSDK.EdsDirectoryItemInfo dirItemInfo;
            err = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);

            // Create a file stream for receiving image.
            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsCreateMemoryStream(dirItemInfo.Size, out stream);
            }

            //  Fill the stream with the resulting image
            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsDownload(directoryItem, dirItemInfo.Size, stream);
            }

            //  Copy the stream to a byte[] and 
            if (err == EDSDK.EDS_ERR_OK)
            {
                byte[] buffer = new byte[dirItemInfo.Size];

                GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                // The following line is where it blows up...
                Marshal.Copy(stream, buffer, 0, (int)dirItemInfo.Size);

                // ... Image manipulation, show user, whatever
            }

            return err;
        }

Los puntos de interrupción revelan (a través del objeto EdsDirectoryItemInfo) que la imagen es de hecho existe, sólo que no sé por qué estaría recibiendo la excepción de que soy. He estado jugando con la idea de aceptar la derrota y acaba de leer la imagen resultante del disco que escribe tan fácilmente mediante el método CreateFileStream, pero realmente debería ser sólo capaz de manipular la imagen en la memoria.

¿Alguna idea?

UPDATE:. Veo este comportamiento en ambas versiones 2.5 y 2.6

¿Fue útil?

Solución

acabo en Google para EdsCreateMemoryStream y encontró un muestra en la que hay otra llamada para obtener el puntero de la" secuencia de memoria ".

IntPtr pointerToBytes;
EDSDKLib.EDSDK.EdsGetPointer(stream, out pointerToBytes);

A continuación, puede utilizar pointerToBytes como la fuente para leer en Marshal.Copy.

Así que supongo que lo que está haciendo actualmente está tratando de copiar algunos gran número de bytes a partir de la dirección de alguna estructura de control pequeña a la que apunta stream, y por lo tanto usted está leyendo más allá del final de esa estructura .

Editar Por cierto, estás código es como si alguien le ha dicho que sólo debe tener una instrucción de retorno! Es un consejo de edad en relación con lenguajes como Fortran y C; que no tiene sentido en lenguas modernas. El código sería más claro (al menos en este caso) si inmediatamente devuelve el código de error cada vez que tienes un fracaso:

if ((err = EDSDK.EdsBlahBlah(...)) != EDSDK.EDS_ERR_OK)
    return err;

(Mejor aún, lanzar una clase de excepción específica que contiene el código de error y una cadena de explicar lo que estaba tratando de hacer.)

Otros consejos

Me doy cuenta de que esta es una entrada antigua, pero esto es una completa fragmento C # para la descarga de una corriente de memoria. Puede ser útil para otra persona. La cámara tiene que ser fijado a EDSDK.EdsSaveTo.Host o EDSDK.EdsSaveTo.Both

        uint error = EDSDK.EDS_ERR_OK;
        IntPtr stream = IntPtr.Zero;

        EDSDK.EdsDirectoryItemInfo directoryItemInfo;

        error = EDSDK.EdsGetDirectoryItemInfo(this.DirectoryItem, out directoryItemInfo);

        //create a file stream to accept the image
        if (error == EDSDK.EDS_ERR_OK)
        {
            error = EDSDK.EdsCreateMemoryStream(directoryItemInfo.Size, out stream);
        }


        //down load image
        if (error == EDSDK.EDS_ERR_OK)
        {
            error = EDSDK.EdsDownload(this.DirectoryItem, directoryItemInfo.Size, stream);
        }

        //complete download
        if (error == EDSDK.EDS_ERR_OK)
        {
            error = EDSDK.EdsDownloadComplete(this.DirectoryItem);
        }


        //convert to memory stream
        IntPtr pointer; //pointer to image stream
        EDSDK.EdsGetPointer(stream, out pointer);

        uint length = 0;
        EDSDK.EdsGetLength(stream, out length);

        byte[] bytes = new byte[length];

        //Move from unmanaged to managed code.
        Marshal.Copy(pointer, bytes, 0, bytes.Length);

        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(bytes);
        Image image = System.Drawing.Image.FromStream(memoryStream);

        if (pointer != IntPtr.Zero)
        {
            EDSDK.EdsRelease(pointer);
            pointer = IntPtr.Zero;
        }


        if (this.DirectoryItem != IntPtr.Zero)
        {
            EDSDK.EdsRelease(this.DirectoryItem);
            this.DirectoryItem = IntPtr.Zero;
        }

        if (stream != IntPtr.Zero)
        {
            EDSDK.EdsRelease(stream);
            stream = IntPtr.Zero;
        }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top