将数据从IntPtr复制到IntPtr

Doc*_*own 28 c#

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

            int length = /* ..*/
            IntPtr ptrSrc = /*.. */;
            IntPtr ptrDst = /* .. */;
Run Code Online (Sandbox Code Playgroud)

现在我想将数据复制ptrSrcptrDst.这段代码工作正常:

            byte[] data = new byte[length];
            Marshal.Copy(ptrSrc, data, 0, length);
            Marshal.Copy(data, 0, ptrDst, length);
Run Code Online (Sandbox Code Playgroud)

但它的缺点是需要一个额外的临时(可能是巨大的)数组.不幸的是,我无法找到一个Marshal.Copy在直接复制.NET框架的变形IntPtrIntPtr,所以我寻找替代品.

我对一个适用于32位Windows和64位Windows的解决方案感兴趣.有什么建议?

dri*_*iis 39

你可以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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您的解决方案似乎在64位模式以及32位模式下工作(在交换源和目标之后;-),请参阅我对您的答案的编辑. (2认同)

use*_*527 14

我认为答案需要在.net 4.6中进行更新

 Buffer.MemoryCopy Method (Void*,?Void*,?Int64,?Int64)
Run Code Online (Sandbox Code Playgroud)

此方法将sourceBytesToCopy字节从source指定的地址复制到destination指定的地址.如果缓冲区重叠且目标减去源之间的差异小于sourceBytesToCopy,则源块将以相反的顺序复制到目标块.

因此,如果你不在4.6或通用Windows应用10上,那么使用前面的答案.


cdi*_*ins 9

正如user38000527 指出的那样,现代答案是MemoryCopy,它是 .NET core 1.0、.NET standard 1.3 和 .NET framework 4.6 的一部分。

以下是您在上下文中使用它的方式:

Buffer.MemoryCopy(ptrSrc.ToPointer(), ptrDest.ToPointer(), length, length) 
Run Code Online (Sandbox Code Playgroud)