|
4 | 4 |
|
5 | 5 | using System.Collections.Generic;
|
6 | 6 | using System.Reflection;
|
7 |
| -using System.Reflection.Emit; |
8 | 7 | using System.Security;
|
9 | 8 | using System.Text;
|
10 | 9 | using System.Runtime.CompilerServices;
|
11 | 10 | using System.Runtime.ConstrainedExecution;
|
12 |
| -using Win32Native = Microsoft.Win32.Win32Native; |
| 11 | +using Microsoft.Win32; |
13 | 12 | using System.Diagnostics;
|
14 | 13 | using System.Runtime.InteropServices.ComTypes;
|
15 | 14 | using System.StubHelpers;
|
16 | 15 |
|
| 16 | +using Internal.Runtime.CompilerServices; |
| 17 | + |
| 18 | +#if BIT64 |
| 19 | +using nuint = System.UInt64; |
| 20 | +#else |
| 21 | +using nuint = System.UInt32; |
| 22 | +#endif // BIT64 |
| 23 | + |
17 | 24 | namespace System.Runtime.InteropServices
|
18 | 25 | {
|
19 | 26 | /// <summary>
|
@@ -238,15 +245,25 @@ public static IntPtr OffsetOf(Type t, string fieldName)
|
238 | 245 |
|
239 | 246 | /// <summary>
|
240 | 247 | /// IMPORTANT NOTICE: This method does not do any verification on the array.
|
241 |
| - /// It must be used with EXTREME CAUTION since passing in an array that is |
242 |
| - /// not pinned or in the fixed heap can cause unexpected results. |
| 248 | + /// It must be used with EXTREME CAUTION since passing in invalid index or |
| 249 | + /// an array that is not pinned can cause unexpected results. |
243 | 250 | /// </summary>
|
244 |
| - [MethodImpl(MethodImplOptions.InternalCall)] |
245 |
| - public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index); |
| 251 | + public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index) |
| 252 | + { |
| 253 | + if (arr == null) |
| 254 | + throw new ArgumentNullException(nameof(arr)); |
246 | 255 |
|
247 |
| - public static IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index) |
| 256 | + void* pRawData = Unsafe.AsPointer(ref arr.GetRawArrayData()); |
| 257 | + return (IntPtr)((byte*)pRawData + (uint)index * (nuint)arr.GetElementSize()); |
| 258 | + } |
| 259 | + |
| 260 | + public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index) |
248 | 261 | {
|
249 |
| - return UnsafeAddrOfPinnedArrayElement((Array)arr, index); |
| 262 | + if (arr == null) |
| 263 | + throw new ArgumentNullException(nameof(arr)); |
| 264 | + |
| 265 | + void* pRawData = Unsafe.AsPointer(ref arr.GetRawSzArrayData()); |
| 266 | + return (IntPtr)((byte*)pRawData + (uint)index * (nuint)Unsafe.SizeOf<T>()); |
250 | 267 | }
|
251 | 268 |
|
252 | 269 | public static void Copy(int[] source, int startIndex, IntPtr destination, int length)
|
@@ -289,8 +306,17 @@ public static void Copy(IntPtr[] source, int startIndex, IntPtr destination, int
|
289 | 306 | CopyToNative(source, startIndex, destination, length);
|
290 | 307 | }
|
291 | 308 |
|
292 |
| - [MethodImpl(MethodImplOptions.InternalCall)] |
293 |
| - private static extern void CopyToNative(object source, int startIndex, IntPtr destination, int length); |
| 309 | + private static unsafe void CopyToNative<T>(T[] source, int startIndex, IntPtr destination, int length) |
| 310 | + { |
| 311 | + if (source == null) |
| 312 | + throw new ArgumentNullException(nameof(source)); |
| 313 | + if (destination == IntPtr.Zero) |
| 314 | + throw new ArgumentNullException(nameof(destination)); |
| 315 | + |
| 316 | + // The rest of the argument validation is done by CopyTo |
| 317 | + |
| 318 | + new Span<T>(source, startIndex, length).CopyTo(new Span<T>((void*)destination, length)); |
| 319 | + } |
294 | 320 |
|
295 | 321 | public static void Copy(IntPtr source, int[] destination, int startIndex, int length)
|
296 | 322 | {
|
@@ -332,9 +358,22 @@ public static void Copy(IntPtr source, IntPtr[] destination, int startIndex, int
|
332 | 358 | CopyToManaged(source, destination, startIndex, length);
|
333 | 359 | }
|
334 | 360 |
|
335 |
| - [MethodImpl(MethodImplOptions.InternalCall)] |
336 |
| - private static extern void CopyToManaged(IntPtr source, object destination, int startIndex, int length); |
337 |
| - |
| 361 | + private static unsafe void CopyToManaged<T>(IntPtr source, T[] destination, int startIndex, int length) |
| 362 | + { |
| 363 | + if (source == IntPtr.Zero) |
| 364 | + throw new ArgumentNullException(nameof(source)); |
| 365 | + if (destination == null) |
| 366 | + throw new ArgumentNullException(nameof(destination)); |
| 367 | + if (startIndex < 0) |
| 368 | + throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex); |
| 369 | + if (length < 0) |
| 370 | + throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum); |
| 371 | + |
| 372 | + // The rest of the argument validation is done by CopyTo |
| 373 | + |
| 374 | + new Span<T>((void*)source, length).CopyTo(new Span<T>(destination, startIndex, length)); |
| 375 | + } |
| 376 | + |
338 | 377 | public static byte ReadByte(object ptr, int ofs)
|
339 | 378 | {
|
340 | 379 | return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => ReadByte(nativeHome, offset));
|
@@ -837,6 +876,9 @@ public static object PtrToStructure(IntPtr ptr, Type structureType)
|
837 | 876 |
|
838 | 877 | public static void DestroyStructure<T>(IntPtr ptr) => DestroyStructure(ptr, typeof(T));
|
839 | 878 |
|
| 879 | + [MethodImpl(MethodImplOptions.InternalCall)] |
| 880 | + internal static extern bool IsPinnable(object obj); |
| 881 | + |
840 | 882 | #if FEATURE_COMINTEROP
|
841 | 883 | /// <summary>
|
842 | 884 | /// Returns the HInstance for this module. Returns -1 if the module doesn't have
|
|
0 commit comments