If you want to do a memory copy between two arrays, there's an Array.Copy
function for that in .NET:
char[] GetCopy(char[] buf)
{
char[] result = new char[buf.Length];
Array.Copy(buf, result);
return result;
}
This is usually faster than manually for-looping to copy all the characters in buf
to result
, because it's a block copy operation that simply takes a chunk of memory and writes it to the destination.
Similarly, if I was instead given a char*
and an int
specifying its size, what are my options? Here are the ones I've considered:
src
and dst
to be arraysOr, if there's no alternative, is there some kind of way to construct an array from a pointer char*
and a length int
? If I could do that, I could just convert the pointers to arrays and pass them into Array.Copy.
I'm not looking for for-loops because as I said they're not very efficient compared to block copies, but if that's the only way I guess that would have to do.
TL;DR: I'm basically looking for memcpy()
, but in C# and can be used in PCLs.
You state that Marshal.Copy
would not be supported any longer, however on the documentation of the Marshal class i can find no indication for that.
Quite the contrary, the class is available for the following framework versions: 4.6, 4.5, 4, 3.5, 3.0, 2.0, 1.1
One possible implementation of a utility function based on this method would be:
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));
}
However, it is quite possible, that copying the bytes from IntPtr
to byte[]
and back again negates any possible performance gain over pinning the unsafe memory and copying it in a loop.
Depending on how portable the code needs to be, you could also consider using P/Invoke to actually use the memcpy
method. This should work well on Windows 2000 and onwards (all systems that have the Microsoft Visual C Run-Time Library installed).
[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
static extern IntPtr memcpy(IntPtr dst, IntPtr src, UIntPtr count);
Edit: The second approach would not be suited for portable class libraries, the first however would be.
I don't recall what built-in APIs the BCL has but you can copy the BCL memcpy
code and use it. Use Reflector and search for "memcpy" to find it. Unsafe code is perfectly defined and portable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With