可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have two unmanaged pointers in the form of IntPtr and want to copy data between them. How can I do this? I know the method Marshal.Copy, but it can only copy between unmanaged and managed. And the second part: Is copying unmanaged data from C# slower than doing it in unmanaged C/C++ using memcpy?
Edit: I would be especially interested in a platform independet implementation.
回答1:
You can use the win32 memcpy function via P-Invoke.
[DllImport("msvcrt.dll", SetLastError = false)] static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count);
Apart from the (slight) overhead calling a win32 function from managed code, the actual copy performance should be the same as C/C++ code that uses the same function.
Don't forget that you can also use an unsafe block (and compiler option) and simply copy the data one byte/int/long at a time:
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
This removes the platform dependency, but you need to be very careful with the bounds checking and pointer arithmetic.
回答2:
Without making comments on performance, purely because I have not tested it. You can achieve the same performance as unmanaged copy by using either CopyMemory or MoveMemory from Kernel32 via interop.
Here is the declaration for CopyMemory
[DllImport("kernel32.dll")] static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
回答3:
If you can target .NET 4.6 or higher, try System.Buffer.MemoryCopy. I believe that the main difference between this and the P/Invoke solutions listed above is that this method avoids the P/Invoke for smaller sizes and just does the copying directly.
Here's the guts of the implementation in .NET Core (latest as of the time of this posting).
回答4:
CopyMemory aka RtlCopyMemory aka memcpy() will be just as fast whether called from C# or C (other than the tiny overhead of PInvoking the method itself).
Something to keep in mind, though, is that CopyMemory should only be used when you're sure that the source and destination ranges do not overlap. If they do overlap, you need to use MoveMemory instead, which will be slower.
Here is a declaration for CopyMeSomeMemory, showing how many different ways you can do the same thing in .Net:
[DllImport("kernel32.dll", EntryPoint = "RtlCopyMemory")] public static extern void CopyMeSomeMemory(IntPtr Destination, IntPtr Source, uint Length);
For the record, I think Buffer.BlockCopy in .Net just wraps one of these functions, too.