将数据从IntPtr复制到IntPtr

本文关键字:IntPtr 复制 数据 | 更新日期: 2023-09-27 18:09:06

我有两个IntPtr值指向length字节的一些数据区域。length可能有200k到400k的数量级。

int length = /* ..*/
IntPtr ptrSrc = /*.. */;
IntPtr ptrDst = /* .. */;

现在我想把数据从ptrSrc复制到ptrDst。下面的代码运行良好:

byte[] data = new byte[length];
Marshal.Copy(ptrSrc, data, 0, length);
Marshal.Copy(data, 0, ptrDst, length);

,但它的缺点是需要额外的临时(可能很大)数组。不幸的是,我无法在。net框架中找到直接从IntPtr复制到IntPtrMarshal.Copy变体,因此我正在寻找替代方案。

我对一个既能在32位Windows上工作又能在64位Windows上工作的解决方案感兴趣。有什么建议吗?

将数据从IntPtr复制到IntPtr

您可以p/Invoke到适当的C函数中。这可能是最简单的方法。例子:

class Program
{
    [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
    public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
    static void Main()
    {
        const int size = 200;
        IntPtr memorySource = Marshal.AllocHGlobal(size);
        IntPtr memoryTarget = Marshal.AllocHGlobal(size);
        CopyMemory(memoryTarget,memorySource,size);
    }
}

我认为答案需要在。net 4.6中更新

 Buffer.MemoryCopy Method (Void*, Void*, Int64, Int64)

该方法从源指定的地址复制sourceBytesToCopy字节到目的指定的地址。如果缓冲区重叠,并且destination - source之间的差值小于sourceBytesToCopy,则源块以相反的顺序复制到目标块。

所以如果你不是在4.6或通用windows应用程序10,那么使用前面的答案

正如user38000527指出的那样,现代的答案是MemoryCopy,它是。net核心1.0,。net标准1.3和。net框架4.6的一部分。

在上下文中如何使用:

Buffer.MemoryCopy(ptrSrc.ToPointer(), ptrDest.ToPointer(), length, length) 

老问题,新答案…

使用Span<T>工作很棒,非常快。平台independend。

dotnet core 2.1及更高版本的最佳方法是:

var srcSpan = new Span<byte>(srcPtr, count);
var dstSpan = new Span<byte>(dstPtr, count);
srcSpan.CopyTo(dstSpan);

,或者简化:

public static void CopyMemory(void* srcPtr, void* dstPtr, int count) =>
   new Span<byte>(srcPtr, count).CopyTo(new Span<byte>(dstPtr, count));