在C#中,IntPtr
通常用于表示非托管内存的指针。将 IntPtr
转换为字节数组以及从字节数组返回 IntPtr
是常见的操作,尤其在处理P/Invoke调用、内存映射文件或COM互操作时非常有用。以下是如何进行这些转换的详细说明和示例代码。
IntPtr
转换为字节数组要将 IntPtr
指向的内存内容复制到字节数组中,可以使用 Marshal.Copy
方法。该方法允许你指定源指针、目标字节数组以及要复制的字节数。
using System;
using System.Runtime.InteropServices;
public class IntPtrToByteArray
{
public static byte[] IntPtrToByteArray(IntPtr ptr, int length)
{
byte[] byteArray = new byte[length];
Marshal.Copy(ptr, byteArray, 0, length);
return byteArray;
}
// 示例用法
public static void Main()
{
// 假设我们有一个非托管内存块,包含一些字节数据
byte[] originalData = { 0x01, 0x02, 0x03, 0x04, 0x05 };
IntPtr ptr = Marshal.AllocHGlobal(originalData.Length);
try
{
// 将字节数组复制到非托管内存
Marshal.Copy(originalData, 0, ptr, originalData.Length);
// 将非托管内存转换回字节数组
byte[] copiedData = IntPtrToByteArray(ptr, originalData.Length);
Console.WriteLine("Copied Data:");
foreach (byte b in copiedData)
{
Console.Write($"{b:X2} ");
}
}
finally
{
// 释放非托管内存
Marshal.FreeHGlobal(ptr);
}
}
}
Copied Data:
01 02 03 04 05
IntPtr
要将字节数组的内容复制到非托管内存并获取其 IntPtr
,可以使用 Marshal.AllocHGlobal
分配内存,然后使用 Marshal.Copy
将字节数组复制到该内存中。
using System;
using System.Runtime.InteropServices;
public class ByteArrayToIntPtr
{
public static IntPtr ByteArrayToIntPtr(byte[] byteArray)
{
IntPtr ptr = Marshal.AllocHGlobal(byteArray.Length);
try
{
Marshal.Copy(byteArray, 0, ptr, byteArray.Length);
return ptr;
}
catch
{
Marshal.FreeHGlobal(ptr);
throw;
}
}
// 示例用法
public static void Main()
{
byte[] data = { 0xAA, 0xBB, 0xCC, 0xDD };
IntPtr ptr = ByteArrayToIntPtr(data);
// 使用 ptr 进行需要的操作...
// 当不再需要时,释放非托管内存
Marshal.FreeHGlobal(ptr);
}
}
Marshal.AllocHGlobal
分配的非托管内存不会被垃圾回收器自动释放。必须手动调用 Marshal.FreeHGlobal
来释放内存,以避免内存泄漏。除了 Marshal.Copy
,还可以使用 Buffer.BlockCopy
或 unsafe 代码块进行更高效的内存操作。但是,Marshal.Copy
是处理非托管内存和托管字节数组之间转换的最安全和最简单的方法。
Buffer.BlockCopy
的示例public static byte[] IntPtrToByteArrayUsingBlockCopy(IntPtr ptr, int length)
{
byte[] byteArray = new byte[length];
unsafe
{
fixed (byte* pBytes = byteArray)
{
Buffer.MemoryCopy(ptr.ToPointer(), pBytes, length, length);
}
}
return byteArray;
}
不过,通常情况下,Marshal.Copy
已经足够满足大多数需求,并且更易于理解和维护。
通过上述方法,你可以在C#中方便地在 IntPtr
和字节数组之间进行转换,从而有效地处理非托管内存和数据交互。
领取专属 10元无门槛券
手把手带您无忧上云