不安全的 C#:如何将数据从 IntPtr 复制到 byte*?
Unsafe C#: How do I copy data from IntPtr to byte*?
在我的(不安全的).Net 应用程序中,我有一个 IntPtr 引用位图中的像素数据块(第三方图像的一部分 class)。我还有一个结构,其中包含一个 fixed 字节数组,其大小足以包含 8*1024*1024 字节的图像数据。
(代码片段显示了共享内存中存在的结构的简化版本。)
我在这个 post (How can I pin an array of byte?) 中看到为类似问题提供了解决方案,但它适用于 byte[],在这种情况下,编译器认为我的 "ImageData"字段是一个字节*。当然,它不会让我在 byte* 和 byte[] 之间转换或转换,安全或不安全。
那么,如何才能将数据从我的 IntPtr(或任何其他数组)复制到我的 MyDecoder->ImageData 中?
(无论是否使用中间 IntPtr,最终目标是将托管 (RGBA) 像素数据复制到非托管字节*位置。)
[StructLayout(LayoutKind.Explicit)]
unsafe public struct SharedMemMPEG2Decode
{
[FieldOffset(0)] public UInt32 Width; // Width of the image
[FieldOffset(4)] public UInt32 Height; // Height of the image
[FieldOffset(8)] public UInt32 FourCC; // Data format identifier
[FieldOffset(12)] public UInt32 ImageSize; // Size of the image data in bytes
// ...
[FieldOffset(16896)] public unsafe fixed byte ImageData[8 * 1024 * 1024];
}
// ...
// This pointer is initialized with MemoryMappedViewAccessor.SafeMemoryMappedViewHandle.AcquirePointer():
SharedMemMPEG2Decode *MyDecoder;
// ...
IntPtr xfer_buffer = Marshal.AllocHGlobal(8 * 1024 * 1024);
// ...
// Not shown: Copy of pixel data from 3rd party Image class to the above buffer
Marshal.Copy(xfer_buffer, MyDecoder->ImageData, 0, image_size_bytes); // b0rken! Won't compile
首先,您当然需要确保垃圾收集器不会移动源和目标;我想你可以正确地做到这一点。
要高效地进行内存复制:
- 将
IntPtr
转换为 byte*
- 使用
fixed
语句从固定大小的数组中获取一个byte*
。 (是的,不幸的是 C# 使用 fixed
表示 "fixed in size" 和 "fixed in place")
- 现在你有两个
byte*
,你可以使用 System.Buffer.MemoryCopy
。
详情见https://docs.microsoft.com/en-us/dotnet/api/system.buffer.memorycopy?view=netframework-4.7.2。
在我的(不安全的).Net 应用程序中,我有一个 IntPtr 引用位图中的像素数据块(第三方图像的一部分 class)。我还有一个结构,其中包含一个 fixed 字节数组,其大小足以包含 8*1024*1024 字节的图像数据。
(代码片段显示了共享内存中存在的结构的简化版本。)
我在这个 post (How can I pin an array of byte?) 中看到为类似问题提供了解决方案,但它适用于 byte[],在这种情况下,编译器认为我的 "ImageData"字段是一个字节*。当然,它不会让我在 byte* 和 byte[] 之间转换或转换,安全或不安全。
那么,如何才能将数据从我的 IntPtr(或任何其他数组)复制到我的 MyDecoder->ImageData 中?
(无论是否使用中间 IntPtr,最终目标是将托管 (RGBA) 像素数据复制到非托管字节*位置。)
[StructLayout(LayoutKind.Explicit)]
unsafe public struct SharedMemMPEG2Decode
{
[FieldOffset(0)] public UInt32 Width; // Width of the image
[FieldOffset(4)] public UInt32 Height; // Height of the image
[FieldOffset(8)] public UInt32 FourCC; // Data format identifier
[FieldOffset(12)] public UInt32 ImageSize; // Size of the image data in bytes
// ...
[FieldOffset(16896)] public unsafe fixed byte ImageData[8 * 1024 * 1024];
}
// ...
// This pointer is initialized with MemoryMappedViewAccessor.SafeMemoryMappedViewHandle.AcquirePointer():
SharedMemMPEG2Decode *MyDecoder;
// ...
IntPtr xfer_buffer = Marshal.AllocHGlobal(8 * 1024 * 1024);
// ...
// Not shown: Copy of pixel data from 3rd party Image class to the above buffer
Marshal.Copy(xfer_buffer, MyDecoder->ImageData, 0, image_size_bytes); // b0rken! Won't compile
首先,您当然需要确保垃圾收集器不会移动源和目标;我想你可以正确地做到这一点。
要高效地进行内存复制:
- 将
IntPtr
转换为byte*
- 使用
fixed
语句从固定大小的数组中获取一个byte*
。 (是的,不幸的是 C# 使用fixed
表示 "fixed in size" 和 "fixed in place") - 现在你有两个
byte*
,你可以使用System.Buffer.MemoryCopy
。
详情见https://docs.microsoft.com/en-us/dotnet/api/system.buffer.memorycopy?view=netframework-4.7.2。