Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I copy unmanaged data in C# and how fast is it?

Tags:

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.

like image 455
Danvil Avatar asked Apr 17 '10 12:04

Danvil


3 Answers

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 < size / sizeof(long); i++)
    {
        dest[i] = src[i];
    }
}

This removes the platform dependency, but you need to be very careful with the bounds checking and pointer arithmetic.

like image 99
Ash Avatar answered Oct 16 '22 01:10

Ash


Try System.Buffer.MemoryCopy, see the bottom of the page for supported target frameworks.

I believe that the main difference between this and the other solutions that use P/Invoke 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 2020-09-04).

like image 24
Joe Amenta Avatar answered Oct 15 '22 23:10

Joe Amenta


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);
like image 30
Chris Taylor Avatar answered Oct 15 '22 23:10

Chris Taylor