c# - 佳能 EDSDK 内存流图像

标签 c# dll unmanaged edsdk

我与 Canon EDSDK 的斗争已经有一段时间了。我可以成功地让库将文件直接保存到磁盘,但是,我无法在内存中获取图像 byte[]。每当我尝试将 EDSDK 流 Marshal.Copy() 到 byte[] 时,我总是会收到以下错误:

AccessViolationException:试图读取或写入 protected 内存。这通常表明其他内存已损坏。

下面是我用来尝试获取流的代码变体之一:

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

断点显示(通过 EdsDirectoryItemInfo 对象)图像确实存在,我只是不知道为什么我会得到我所在的异常。我一直在玩弄接受失败的想法,只是从磁盘中读取生成的图像,它很容易通过 CreateFileStream 方法写入,但我真的应该能够在内存中操作图像。

有什么想法吗?

更新:我在 2.5 和 2.6 版本中都看到了这种行为。

最佳答案

我刚刚在谷歌上搜索了 EdsCreateMemoryStreamfound a sample其中还有另一个从“内存流”中获取指针的调用。

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

然后您可以使用 pointerToBytes 作为在 Marshal.Copy 中读取的源。

所以我猜你目前正在做的是尝试从 stream 指向的一些小控制结构的地址开始复制大量字节,因此你是阅读该结构的末尾。

编辑:顺便说一句,您的代码看起来好像有人告诉您您应该只有一个返回语句!这是与 Fortran 和 C 等语言相关的旧建议;它在现代语言中没有意义。如果您在每次失败时立即返回错误代码,您的代码会更清晰(至少在这种情况下):

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

(更好的是,抛出一个特定的异常类,其中包含错误代码和一个解释您尝试执行的操作的字符串。)

关于c# - 佳能 EDSDK 内存流图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1083446/

相关文章:

c# - ThreadPool 挫折 - 线程创建超过 SetMaxThreads

c# - 当我将图像提供给经过训练的模型时,它为未在模型中训练的对象提供了 80% 以上的准确度

c++ - 有没有办法在加载 dll 时调试发布版本?

c# - 堆栈不平衡问题

c# - 使用 c# 将委托(delegate)传递给非托管代码中的回调函数

c# - 在 C# 中使用 DLL

c++ - 获取十六进制字符串的字节长度的替代方法

c# - MVC 中的 Razor 页面出现编译错误,未找到 System.Web.Helpers

c# - 在哪里可以找到要添加为引用的 Microsoft.VisualStudio.ExtensionManager?

c++ - 链接到 DLL 文件中的 Boost