Last active
June 28, 2019 19:20
-
-
Save ogxd/3db136d5d833f1745f4605045b2ec558 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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