public static T[] __FromPInvoke <T>(SafeArray data) { if (data.Size == 0) { return(new T[0]); } var type = typeof(T); T[] result; if (type.IsValueType) { // Array of structs or builtin types. var size = Marshal.SizeOf <T>(); result = new T[data.Size / size]; var handle = GCHandle.Alloc(result, GCHandleType.Pinned); Buffer.MemoryCopy((void *)data.Data, (void *)handle.AddrOfPinnedObject(), data.Size, data.Size); handle.Free(); } else { // Array of pointers to objects var tFromPInvoke = type.GetMethod("__FromPInvoke", BindingFlags.NonPublic | BindingFlags.Static); var pointers = (void **)data.Data; Debug.Assert(pointers != null); Debug.Assert(tFromPInvoke != null); var count = data.Size / IntPtr.Size; result = new T[count]; for (int i = 0; i < count; i++) { result[i] = (T)tFromPInvoke.Invoke(null, new object[] { new IntPtr(pointers[i]) }); } } if (data.Owns) { MarshalTools.c_free(data.Data); } return(result); }
public static SafeArray __ToPInvoke <T>(T[] data) { if (data == null) { return(new SafeArray()); } var type = typeof(T); var result = new SafeArray { Owns = true }; if (type.IsValueType) { // Array of structs or builtin types. result.Size = data.Length * Marshal.SizeOf <T>(); result.Data = MarshalTools.c_alloc(result.Size); var handle = GCHandle.Alloc(result, GCHandleType.Pinned); Buffer.MemoryCopy((void *)handle.AddrOfPinnedObject(), (void *)result.Data, result.Size, result.Size); handle.Free(); } else { // Array of pointers to objects result.Size = data.Length * IntPtr.Size; result.Data = MarshalTools.c_alloc(result.Size); var tToPInvoke = type.GetMethod("__ToPInvoke", BindingFlags.NonPublic | BindingFlags.Static); var pointers = (void **)result.Size; Debug.Assert(tToPInvoke != null); Debug.Assert(pointers != null); for (var i = 0; i < data.Length; i++) { pointers[i] = ((IntPtr)tToPInvoke.Invoke(null, new object[] { data[i] })).ToPointer(); } } return(result); }