views:

1338

answers:

1

I've been fighting with the Canon EDSDK for a while now. I can successfully get the library to save a file directly to disk, however, I cannot get a hold of the image byte[] in memory. Whenever I attempt to Marshal.Copy() the EDSDK Stream to byte[], I always get the following error:

AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Below is one of the variations of code that I've used to try and get the stream:

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

Breakpoints reveal (Through the EdsDirectoryItemInfo object) that the image is indeed there, I just don't know why I'd be getting the exception that I am. I have been toying with the idea of accepting defeat and just read the resultant image from disk that it so readily writes via the CreateFileStream method, but I really ought to just be able to manipulate the image in memory.

Any ideas?

UPDATE: I see this behavior in both versions 2.5 and 2.6.

+2  A: 

I just googled for EdsCreateMemoryStream and found a sample in which there's another call to get the pointer from the "memory stream".

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

You can then use pointerToBytes as the source to read from in Marshal.Copy.

So I'd guess that what you're currently doing is attempting to copy some large number of bytes starting from the address of some small control structure pointed to by stream, and hence you're reading past the end of that structure.

Edit: By the way, you're code looks as if someone's told you that you should only have one return statement! That's old advice relating to languages like Fortran and C; it doesn't make sense in modern languages. Your code would be clearer (at least in this case) if you immediately returned the error code every time you got a failure:

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

(Better yet, throw a specific exception class containing the error code and a string explaining what you were trying to do.)

Daniel Earwicker
This particular method is just a wrapper method (a test one at that) for the EDSDK, so duelly noted. I'll give the pointer read a try when I get home.
Wayne Hartman