【问题标题】:Access Violation Exception using the method Marshal.Copy()使用 Marshal.Copy() 方法的访问冲突异常
【发布时间】:2014-07-04 21:31:42
【问题描述】:

我正在使用 .NET 编写一个简单的 OpenCV 应用程序,其目标是在一个简单的窗口上呈现网络摄像头流。

这是我用来执行此操作的代码:

private static BitmapSource ToBitmapSource(IImage image)
{
    using (System.Drawing.Bitmap source = image.Bitmap)
    {
        IntPtr ptr = source.GetHbitmap();
        BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            ptr,
            IntPtr.Zero,
            Int32Rect.Empty,
            System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        DeleteObject(ptr);
        return bs;
    }
}

private void CameraShow()
{
    ImageViewer viewer = new Emgu.CV.UI.ImageViewer(); //create an image viewer
    Capture capture = new Capture(); //create a camera captue

    this.isCamOff = false;
    while (this.CamStat != eCamRun.CamStop)
    {
        Thread.Sleep(60);
        viewer.Image = capture.QueryFrame(); //draw the image obtained from camera
        System.Windows.Application.Current.Dispatcher.Invoke(
            DispatcherPriority.Normal,
            (ThreadStart)delegate
        {
            this.ImageStream.Source = ToBitmapSource(viewer.Image); //BitmapSource
        });
    }

    viewer.Dispose();
    capture.Dispose();
    this.isCamOff = true;
    Thread.CurrentThread.Interrupt();
}

但是现在我想在控制台上显示包含在 System.Drawing.Bitmap 对象中的像素缓冲区的内容(我知道 void* 本机类型包含在 Bitmap 对象的 IntPtr 变量中)。因此,根据我下面的源代码来恢复 IntPtr 变量,我必须编写以下代码行(进入“不安全”上下文):

IntPtr buffer = viewer.Image.Bitmap.GetHbitmap();

byte[] pPixelBuffer = new byte[16]; //16 bytes allocation
Marshal.Copy(buffer, pPixelBuffer, 0, 9); //I copy the 9 first bytes into pPixelBuffer

不幸的是,我在“复制”方法中遇到了访问冲突异常!我不明白为什么。

有人可以帮帮我吗?

非常感谢您的帮助。

【问题讨论】:

    标签: c# emgucv intptr opencvsharp


    【解决方案1】:

    您可以在不安全的上下文中将IntPtr 强制转换为void*。你可以这样做:

    unsafe
    {
        var bytePtr = (byte*)(void*)buffer;
    
        // Here use *bytePtr to get the byte value at bytePtr, just like in C/C++
    }
    

    【讨论】:

    • @AlexD 当您的指针指向从本机 API 获取的资源时不会。 GC 只能重定位 .NET 对象,而 fixed 会阻止这种情况。本机对象不会在内存中移动。
    • 你在解释我无法打印帧视频缓冲区,因为 EMGU 使用了原生 API?因此,如果 Visual Studio 调试器显示我的“ptr”指针是无效指针,这很正常吗?所以我不能打印它的内容?
    • @user1364743 我不是这样说的。我的评论是对之前被删除的评论的回应。我不知道emgu,但是只要IntPtr不为零,它就指向一些数据,你应该可以用答案的方法读取那个数据。如果您的缓冲区指向视频帧,您应该能够读取它。
    【解决方案2】:

    使用Marshal.Copy怎么样?有了这个,您可以将IntPtr的内容复制到byte[],而无需进入unsafe

    http://msdn.microsoft.com/en-us/library/ms146631(v=vs.110).aspx

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 2014-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-01
      • 2012-11-14
      相关资源
      最近更新 更多