是否有一种可移植的方式来复制C#中的内存块?

时间:2015-08-11 02:20:37

标签: c# arrays pointers copy memcpy

如果你想在两个数组之间进行内存复制,那么在.NET中有一个Array.Copy函数:

char[] GetCopy(char[] buf)
{
    char[] result = new char[buf.Length];
    Array.Copy(buf, result);
    return result;
}

这通常比手动for循环更快地将buf中的所有字符复制到result,因为它是一个块复制操作,只占用一块内存并将其写入目的地。

同样,如果给我char*int指定其大小,我有什么选择?以下是我考虑过的内容:

  • Buffer.BlockCopy :要求srcdst为数组
  • Buffer.MemoryCopy :我正在寻找的,但只能在.NET桌面上使用
  • Marshal.Copy :已停止在.NET 2.0中受支持

或者,如果没有其他选择,是否有某种方法可以从指针char*和长度int构建数组?如果我能做到这一点,我可以将指针转换为数组并将它们传递给Array.Copy。

我不是在寻找for循环,因为正如我所说,与块副本相比,它们并不是非常有效,但如果这是我认为必须做的唯一方法。< / p>

TL; DR:我基本上都在寻找memcpy(),但在C#中可以在PCL中使用。

2 个答案:

答案 0 :(得分:3)

您声明不再支持Marshal.Copy,但是在Marshal类的文档中,我找不到任何迹象。

恰恰相反,该类可用于以下框架版本:4.6,4.5,4,3.5,3.0,2.0,1.1

基于此方法的效用函数的一种可能实现方式是:

public static void CopyFromPtrToPtr(IntPtr src, uint srcLen,
                                    IntPtr dst, uint dstLen)
{
    var buffer = new byte[srcLen];
    Marshal.Copy(src, buffer, 0, buffer.Length);
    Marshal.Copy(buffer, 0, dst, (int)Math.Min(buffer.Length, dstLen));
}

但是,很有可能将字节从IntPtr复制到byte[]并再次返回,从而抵消了固定不安全内存并将其复制到循环中的任何可能的性能提升。

根据代码的可移植性,您还可以考虑使用P / Invoke实际使用memcpy方法。这应该适用于Windows 2000及更高版本(所有安装了Microsoft Visual C运行时库的系统)。

[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
static extern IntPtr memcpy(IntPtr dst, IntPtr src, UIntPtr count);

编辑:第二种方法不适用于可移植类库,但第一种方法是。

答案 1 :(得分:1)

我不记得BCL有哪些内置API,但您可以复制BCL memcpy代码并使用它。使用反射器并搜索&#34; memcpy&#34;找到它。不安全的代码是完美定义和可移植的。