gpt4 book ai didi

c# - 判断 IntPtr 是指向托管内存还是非托管内存

转载 作者:行者123 更新时间:2023-11-30 14:55:18 31 4
gpt4 key购买 nike

我在 C# 中使用包装的 C 库,需要将图像从该库转换为位图并返回,但没有复制像素缓冲区。

转换为位图很简单:

Bitmap WrapAsBitmap(CImage image)
{
return new Bitmap(image.Width, image.Height, image.BytesPerLine, PixelFormat.Format24bppRgb, image.Data);
}

只需将原始像素缓冲区 (image.Data) 传递给 Bitmap 构造函数,无需复制。相反,我需要调用 LockBitsUnlockBits 来访问原始像素缓冲区的 IntPtr:

CImage WrapAsCImage(Bitmap bitmap)
{
BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
var image = new CImage(bitmap.Width, bitmap.Height, data.Stride * 3, data.Scan0);
bitmap.UnlockBits(data);
return image;
}

现在,如您所见,如果 data.Scan0 在托管内存中,这实际上是一种危险的方法,因为这些位在新构造的 image 之前被“解锁” > 将被使用。如果 bitmap 是从 WrapAsBitmap 方法构造的,那么就没有问题,因为 data.Scan0 指向不会被移动的非托管内存。网。因此,我想构建一个安全检查来检查 data.Scan0 指针的位置(托管/非托管)。

我想到的另一个解决方案是继承 Bitmap 类并跟踪原始指针 image.Data 以及 Bitmap,但是 Bitmap 类是密封的,所以我运气不好。

简而言之:有什么想法可以检测 IntPtr 的位置(托管/非托管)吗?

最佳答案

在任何情况下 IntPtr 永远 都不会指向托管内存。当然不是当图像数据是由 C 代码生成的时候。不是当它是由 Bitmap 生成时,GDI+ 是非托管代码。您可以自己推理,您只能通过固定它来获得托管内存的 IntPtr。 GCHandle.AddrOfPinnedObject()。防止垃圾收集器在压缩堆时使指针无效的硬性要求。您在任何地方都看不到需要固定的记录。

实现测试没有意义。

确实有一个非常严格的要求,即在 Bitmap 包装器的生命周期内保持 IntPtr 有效。直到您调用其 Dispose() 方法为止。除了将 Bitmap 对象封装在一个实现 IDisposable 本身的类中之外,您不能使它变得自动。不这样做会导致非常丑陋的错误行为,您只会在幸运时得到 AccessViolationException。具有随机像素内容的损坏位图是正常的故障模式。

如果您不能实现该保证,那么您应该这样做,而是复制位图数据。实现起来并不难,只是不够漂亮。

关于c# - 判断 IntPtr 是指向托管内存还是非托管内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25723336/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com