如何在C#中复制非托管数据以及速度有多快?

我有两个IntPtrforms的非托管指针,并希望在它们之间复制数据。 我怎样才能做到这一点? 我知道方法Marshal.Copy ,但它只能在非托管和托管之间进行复制。 第二部分:使用memcpy从C#中复制非托管数据比使用非托管C / C ++更慢吗?


编辑:我对平台独立实现特别感兴趣。

您可以通过P-Invoke使用win32 memcpy函数。

 [DllImport("msvcrt.dll", SetLastError = false)] static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count); 

除了从托管代码调用win32函数的(轻微)开销之外,实际的复制性能应该与使用相同函数的C / C ++代码相同。

不要忘记您也可以使用不安全的块(和编译器选项),并且一次只能复制一个字节/ int / long的数据:

 unsafe { // srcPtr and destPtr are IntPtr's pointing to valid memory locations // size is the number of long (normally 4 bytes) to copy long* src = (long*)srcPtr; long* dest = (long*)destPtr; for (int i = 0; i < size / sizeof(long); i++) { dest[i] = src[i]; } } 

这将删除平台依赖关系,但您需要非常小心边界检查和指针算法。

没有对性能发表评论,纯粹是因为我没有测试过它。 通过使用来自内核的Kernel32中的CopyMemory或MoveMemory,您可以获得与非托管副本相同的性能。

这是CopyMemory的声明

 [DllImport("kernel32.dll")] static extern void CopyMemory(IntPtr destination, IntPtr source, uint length); 

如果可以使用.NET 4.6或更高版本,请尝试使用System.Buffer.MemoryCopy 。 我相信这个和使用P / Invoke的其他解决方案之间的主要区别在于,这种方法避免了较小尺寸的P / Invoke,只是直接进行复制。

以下是 .NET Core中实现的内容(最新版本为2018-06-19)。

CopyMemory又名RtlCopyMemory又名memcpy() ,无论是从C#还是C调用都是一样快(除了PInvoking方法本身的微小开销)。

但要记住的是,只有当您确定源和目标范围不重叠时才应使用CopyMemory 。 如果它们重叠,则需要使用MoveMemory ,这将更慢。

这是CopyMeSomeMemory的声明,显示了在.Net中可以执行相同操作的不同方法:

 [DllImport("kernel32.dll", EntryPoint = "RtlCopyMemory")] public static extern void CopyMeSomeMemory(IntPtr Destination, IntPtr Source, uint Length); 

为了记录,我认为.Net中的Buffer.BlockCopy也包含了其中一个function。