Skip to content

Instantly share code, notes, and snippets.

@ogxd
Last active June 28, 2019 19:20
Show Gist options
  • Save ogxd/3db136d5d833f1745f4605045b2ec558 to your computer and use it in GitHub Desktop.
Save ogxd/3db136d5d833f1745f4605045b2ec558 to your computer and use it in GitHub Desktop.
// The 'unmanaged' keyword was added in C# 7.3, to allow type restriction for unmanaged types (it checks if type has references recursively)
// https://docs.microsoft.com/fr-fr/dotnet/csharp/whats-new/csharp-7-3
#define CSHARP_7_3_OR_ABOVE
// Marshal.SizeOf(Type) was changed for Marshal.SizeOf<T>() in .NET 4.5.1, and the first constructor became obsolete in NET Standard.
// https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.sizeof?view=netframework-4.5
#define NET_4_5_1_OR_ABOVE
using System;
using System.Runtime.InteropServices;
using System.Security;
public static class MarshallingUtils {
[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false), SuppressUnmanagedCodeSecurity]
private static unsafe extern void* msvrt_memcpy(void* dest, void* src, ulong count);
#if CSHARP_7_3_OR_ABOVE
public static unsafe T[] Memcpy<T>(void* nativePtr, int length) where T : unmanaged {
T[] managedArray = new T[length];
GCHandle handle = GCHandle.Alloc(managedArray, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
msvrt_memcpy(ptr.ToPointer(), nativePtr, (ulong)(length * sizeof(T)));
handle.Free();
return managedArray;
}
private static unsafe T[] Memcpy<T>(IntPtr nativeIntPtr, int length) where T : unmanaged {
return Memcpy<T>(nativeIntPtr.ToPointer(), length);
}
#else
public static unsafe T[] Memcpy<T>(void* nativePtr, int length) {
T[] managedArray = new T[length];
GCHandle handle = GCHandle.Alloc(managedArray, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
#if NET_4_5_1_OR_ABOVE
msvrt_memcpy(ptr.ToPointer(), nativePtr, (ulong)(length * Marshal.SizeOf<T>()));
#else
msvrt_memcpy(ptr.ToPointer(), nativePtr, (ulong)(length * Marshal.SizeOf(typeof(T))));
#endif
handle.Free();
return managedArray;
}
private static unsafe T[] Memcpy<T>(IntPtr nativeIntPtr, int length) {
return Memcpy<T>(nativeIntPtr.ToPointer(), length);
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment