diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index 623c28f92bde6..6e86818b1d237 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -875,6 +875,7 @@
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ArrayMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ArrayMarshaller.cs
index 07386d0864c62..3803812953ca7 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ArrayMarshaller.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ArrayMarshaller.cs
@@ -10,147 +10,138 @@ namespace System.Runtime.InteropServices.Marshalling
/// Marshaller for arrays
///
/// Array element type
+ /// The unmanaged type for the element type
[CLSCompliant(false)]
- [CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder[]),
- CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
- Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
- public unsafe ref struct ArrayMarshaller
+ [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]),
+ MarshalMode.Default,
+ typeof(ArrayMarshaller<,>))]
+ [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]),
+ MarshalMode.ManagedToUnmanagedIn,
+ typeof(ArrayMarshaller<,>.ManagedToUnmanagedIn))]
+ [ContiguousCollectionMarshaller]
+ public static unsafe class ArrayMarshaller
+ where TUnmanagedElement : unmanaged
{
- private readonly int _sizeOfNativeElement;
-
- private T[]? _managedArray;
- private IntPtr _allocatedMemory;
- private Span _span;
-
- ///
- /// Initializes a new instance of the .
- ///
- /// Size of the native element in bytes.
- public ArrayMarshaller(int sizeOfNativeElement)
- : this()
+ public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[]? managed, out int numElements)
{
- _sizeOfNativeElement = sizeOfNativeElement;
- }
-
- ///
- /// Initializes a new instance of the .
- ///
- /// Array to be marshalled.
- /// Size of the native element in bytes.
- public ArrayMarshaller(T[]? array, int sizeOfNativeElement)
- : this(array, Span.Empty, sizeOfNativeElement)
- { }
-
- ///
- /// Initializes a new instance of the .
- ///
- /// Array to be marshalled.
- /// Buffer that may be used for marshalling.
- /// Size of the native element in bytes.
- ///
- /// The must not be movable - that is, it should not be
- /// on the managed heap or it should be pinned.
- ///
- ///
- public ArrayMarshaller(T[]? array, Span buffer, int sizeOfNativeElement)
- {
- _allocatedMemory = default;
- _sizeOfNativeElement = sizeOfNativeElement;
- if (array is null)
+ if (managed is null)
{
- _managedArray = null;
- _span = default;
- return;
+ numElements = 0;
+ return null;
}
- _managedArray = array;
+ numElements = managed.Length;
// Always allocate at least one byte when the array is zero-length.
- int bufferSize = checked(array.Length * _sizeOfNativeElement);
- int spaceToAllocate = Math.Max(bufferSize, 1);
- if (spaceToAllocate <= buffer.Length)
- {
- _span = buffer[0..spaceToAllocate];
- }
- else
- {
- _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
- _span = new Span((void*)_allocatedMemory, spaceToAllocate);
- }
+ int spaceToAllocate = Math.Max(checked(sizeof(TUnmanagedElement) * numElements), 1);
+ return (TUnmanagedElement*)Marshal.AllocCoTaskMem(spaceToAllocate);
}
- ///
- /// Gets a span that points to the memory where the managed values of the array are stored.
- ///
- /// Span over managed values of the array.
- ///
- public ReadOnlySpan GetManagedValuesSource() => _managedArray;
-
- ///
- /// Gets a span that points to the memory where the unmarshalled managed values of the array should be stored.
- ///
- /// Length of the array.
- /// Span where managed values of the array should be stored.
- ///
- public Span GetManagedValuesDestination(int length) => _allocatedMemory == IntPtr.Zero ? null : _managedArray = new T[length];
-
- ///
- /// Returns a span that points to the memory where the native values of the array are stored after the native call.
- ///
- /// Length of the array.
- /// Span over the native values of the array.
- ///
- public ReadOnlySpan GetNativeValuesSource(int length)
- {
- if (_allocatedMemory == IntPtr.Zero)
- return default;
+ public static ReadOnlySpan GetManagedValuesSource(T[]? managed)
+ => managed;
- int allocatedSize = checked(length * _sizeOfNativeElement);
- _span = new Span((void*)_allocatedMemory, allocatedSize);
- return _span;
- }
+ public static Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
+ => new Span(unmanaged, numElements);
- ///
- /// Returns a span that points to the memory where the native values of the array should be stored.
- ///
- /// Span where native values of the array should be stored.
- ///
- public Span GetNativeValuesDestination() => _span;
-
- ///
- /// Returns a reference to the marshalled array.
- ///
- public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
-
- ///
- /// Returns the native value representing the array.
- ///
- ///
- public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
-
- ///
- /// Sets the native value representing the array.
- ///
- /// The native value.
- ///
- public void FromNativeValue(byte* value)
+ public static T[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
{
- _allocatedMemory = (IntPtr)value;
+ if (unmanaged is null)
+ return null;
+
+ return new T[numElements];
}
- ///
- /// Returns the managed array.
- ///
- ///
- public T[]? ToManaged() => _managedArray;
-
- ///
- /// Frees native resources.
- ///
- ///
- public void FreeNative()
+ public static Span GetManagedValuesDestination(T[]? managed)
+ => managed;
+
+ public static ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements)
+ => new ReadOnlySpan(unmanagedValue, numElements);
+
+ public static void Free(TUnmanagedElement* unmanaged)
+ => Marshal.FreeCoTaskMem((IntPtr)unmanaged);
+
+ public ref struct ManagedToUnmanagedIn
{
- Marshal.FreeCoTaskMem(_allocatedMemory);
+ // We'll keep the buffer size at a maximum of 200 bytes to avoid overflowing the stack.
+ public static int BufferSize { get; } = 0x200 / sizeof(TUnmanagedElement);
+
+ private T[]? _managedArray;
+ private TUnmanagedElement* _allocatedMemory;
+ private Span _span;
+
+ ///
+ /// Initializes the marshaller.
+ ///
+ /// Array to be marshalled.
+ /// Buffer that may be used for marshalling.
+ ///
+ /// The must not be movable - that is, it should not be
+ /// on the managed heap or it should be pinned.
+ ///
+ public void FromManaged(T[]? array, Span buffer)
+ {
+ _allocatedMemory = null;
+ if (array is null)
+ {
+ _managedArray = null;
+ _span = default;
+ return;
+ }
+
+ _managedArray = array;
+
+ // Always allocate at least one byte when the array is zero-length.
+ if (array.Length <= buffer.Length)
+ {
+ _span = buffer[0..array.Length];
+ }
+ else
+ {
+ int bufferSize = checked(array.Length * sizeof(TUnmanagedElement));
+ int spaceToAllocate = Math.Max(bufferSize, 1);
+ _allocatedMemory = (TUnmanagedElement*)NativeMemory.Alloc((nuint)spaceToAllocate);
+ _span = new Span(_allocatedMemory, array.Length);
+ }
+ }
+
+ ///
+ /// Gets a span that points to the memory where the managed values of the array are stored.
+ ///
+ /// Span over managed values of the array.
+ public ReadOnlySpan GetManagedValuesSource() => _managedArray;
+
+ ///
+ /// Returns a span that points to the memory where the unmanaged values of the array should be stored.
+ ///
+ /// Span where unmanaged values of the array should be stored.
+ public Span GetUnmanagedValuesDestination() => _span;
+
+ ///
+ /// Returns a reference to the marshalled array.
+ ///
+ public ref TUnmanagedElement GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
+
+ ///
+ /// Returns the unmanaged value representing the array.
+ ///
+ public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)Unsafe.AsPointer(ref GetPinnableReference());
+
+ ///
+ /// Frees resources.
+ ///
+ public void Free()
+ {
+ NativeMemory.Free(_allocatedMemory);
+ }
+
+ public static ref T GetPinnableReference(T[]? array)
+ {
+ if (array is null)
+ {
+ return ref Unsafe.NullRef();
+ }
+ return ref MemoryMarshal.GetArrayDataReference(array);
+ }
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ContiguousCollectionMarshallerAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ContiguousCollectionMarshallerAttribute.cs
similarity index 100%
rename from src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ContiguousCollectionMarshallerAttribute.cs
rename to src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ContiguousCollectionMarshallerAttribute.cs
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/PointerArrayMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/PointerArrayMarshaller.cs
index 03e2f3d245926..bbfc3baffc423 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/PointerArrayMarshaller.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/PointerArrayMarshaller.cs
@@ -10,151 +10,138 @@ namespace System.Runtime.InteropServices.Marshalling
/// Marshaller for arrays of pointers
///
/// Array element pointer type
+ /// The unmanaged type for the element pointer type
[CLSCompliant(false)]
- [CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder*[]),
- CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
- Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
- public unsafe ref struct PointerArrayMarshaller where T : unmanaged
+ [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]),
+ MarshalMode.Default,
+ typeof(PointerArrayMarshaller<,>))]
+ [CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]),
+ MarshalMode.ManagedToUnmanagedIn,
+ typeof(PointerArrayMarshaller<,>.ManagedToUnmanagedIn))]
+ [ContiguousCollectionMarshaller]
+ public static unsafe class PointerArrayMarshaller
+ where T : unmanaged
+ where TUnmanagedElement : unmanaged
{
- private readonly int _sizeOfNativeElement;
-
- private T*[]? _managedArray;
- private IntPtr _allocatedMemory;
- private Span _span;
-
- ///
- /// Initializes a new instance of the .
- ///
- /// Size of the native element in bytes.
- public PointerArrayMarshaller(int sizeOfNativeElement)
- : this()
+ public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T*[]? managed, out int numElements)
{
- _sizeOfNativeElement = sizeOfNativeElement;
- }
-
- ///
- /// Initializes a new instance of the .
- ///
- /// Array to be marshalled.
- /// Size of the native element in bytes.
- public PointerArrayMarshaller(T*[]? array, int sizeOfNativeElement)
- : this(array, Span.Empty, sizeOfNativeElement)
- { }
-
- ///
- /// Initializes a new instance of the .
- ///
- /// Array to be marshalled.
- /// Buffer that may be used for marshalling.
- /// Size of the native element in bytes.
- ///
- /// The must not be movable - that is, it should not be
- /// on the managed heap or it should be pinned.
- ///
- ///
- public PointerArrayMarshaller(T*[]? array, Span buffer, int sizeOfNativeElement)
- {
- _allocatedMemory = default;
- _sizeOfNativeElement = sizeOfNativeElement;
- if (array is null)
+ if (managed is null)
{
- _managedArray = null;
- _span = default;
- return;
+ numElements = 0;
+ return null;
}
- _managedArray = array;
+ numElements = managed.Length;
// Always allocate at least one byte when the array is zero-length.
- int bufferSize = checked(array.Length * _sizeOfNativeElement);
- int spaceToAllocate = Math.Max(bufferSize, 1);
- if (spaceToAllocate <= buffer.Length)
- {
- _span = buffer[0..spaceToAllocate];
- }
- else
- {
- _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
- _span = new Span((void*)_allocatedMemory, spaceToAllocate);
- }
+ int spaceToAllocate = Math.Max(checked(sizeof(TUnmanagedElement) * numElements), 1);
+ return (TUnmanagedElement*)Marshal.AllocCoTaskMem(spaceToAllocate);
}
- ///
- /// Gets a span that points to the memory where the managed values of the array are stored.
- ///
- /// Span over managed values of the array.
- ///
- public ReadOnlySpan GetManagedValuesSource() => Unsafe.As(_managedArray);
-
- ///
- /// Gets a span that points to the memory where the unmarshalled managed values of the array should be stored.
- ///
- /// Length of the array.
- /// Span where managed values of the array should be stored.
- ///
- public Span GetManagedValuesDestination(int length)
+ public static ReadOnlySpan GetManagedValuesSource(T*[]? managed)
+ => Unsafe.As(managed);
+
+ public static Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
+ => new Span(unmanaged, numElements);
+
+ public static T*[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
{
- if (_allocatedMemory == IntPtr.Zero)
+ if (unmanaged is null)
return null;
- _managedArray = new T*[length];
- return Unsafe.As(_managedArray);
+ return new T*[numElements];
}
- ///
- /// Returns a span that points to the memory where the native values of the array are stored after the native call.
- ///
- /// Length of the array.
- /// Span over the native values of the array.
- ///
- public ReadOnlySpan GetNativeValuesSource(int length)
- {
- if (_allocatedMemory == IntPtr.Zero)
- return default;
+ public static Span GetManagedValuesDestination(T*[]? managed)
+ => Unsafe.As(managed);
- int allocatedSize = checked(length * _sizeOfNativeElement);
- _span = new Span((void*)_allocatedMemory, allocatedSize);
- return _span;
- }
+ public static ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements)
+ => new ReadOnlySpan(unmanagedValue, numElements);
+
+ public static void Free(TUnmanagedElement* unmanaged)
+ => Marshal.FreeCoTaskMem((IntPtr)unmanaged);
- ///
- /// Returns a span that points to the memory where the native values of the array should be stored.
- ///
- /// Span where native values of the array should be stored.
- ///
- public Span GetNativeValuesDestination() => _span;
-
- ///
- /// Returns a reference to the marshalled array.
- ///
- public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
-
- ///
- /// Returns the native value representing the array.
- ///
- ///
- public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
-
- ///
- /// Sets the native value representing the array.
- ///
- /// The native value.
- ///
- public void FromNativeValue(byte* value) => _allocatedMemory = (IntPtr)value;
-
- ///
- /// Returns the managed array.
- ///
- ///
- public T*[]? ToManaged() => _managedArray;
-
- ///
- /// Frees native resources.
- ///
- ///
- public void FreeNative()
+ public ref struct ManagedToUnmanagedIn
{
- Marshal.FreeCoTaskMem(_allocatedMemory);
+ public static int BufferSize => 0x200 / sizeof(TUnmanagedElement);
+
+ private T*[]? _managedArray;
+ private TUnmanagedElement* _allocatedMemory;
+ private Span _span;
+
+ ///
+ /// Initializes the marshaller.
+ ///
+ /// Array to be marshalled.
+ /// Buffer that may be used for marshalling.
+ ///
+ /// The must not be movable - that is, it should not be
+ /// on the managed heap or it should be pinned.
+ ///
+ public void FromManaged(T*[]? array, Span buffer)
+ {
+ _allocatedMemory = null;
+ if (array is null)
+ {
+ _managedArray = null;
+ _span = default;
+ return;
+ }
+
+ _managedArray = array;
+
+ // Always allocate at least one byte when the array is zero-length.
+ if (array.Length <= buffer.Length)
+ {
+ _span = buffer[0..array.Length];
+ }
+ else
+ {
+ int bufferSize = checked(array.Length * sizeof(TUnmanagedElement));
+ int spaceToAllocate = Math.Max(bufferSize, 1);
+ _allocatedMemory = (TUnmanagedElement*)NativeMemory.Alloc((nuint)spaceToAllocate);
+ _span = new Span(_allocatedMemory, array.Length);
+ }
+ }
+
+ ///
+ /// Gets a span that points to the memory where the managed values of the array are stored.
+ ///
+ /// Span over managed values of the array.
+ public ReadOnlySpan GetManagedValuesSource() => Unsafe.As(_managedArray);
+
+ ///
+ /// Returns a span that points to the memory where the unmanaged values of the array should be stored.
+ ///
+ /// Span where unmanaged values of the array should be stored.
+ public Span GetUnmanagedValuesDestination() => _span;
+
+ ///
+ /// Returns a reference to the marshalled array.
+ ///
+ public ref TUnmanagedElement GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
+
+ ///
+ /// Returns the unmanaged value representing the array.
+ ///
+ public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)Unsafe.AsPointer(ref GetPinnableReference());
+
+ ///
+ /// Frees resources.
+ ///
+ public void Free()
+ {
+ NativeMemory.Free(_allocatedMemory);
+ }
+
+ public static ref byte GetPinnableReference(T*[]? array)
+ {
+ if (array is null)
+ {
+ return ref Unsafe.NullRef();
+ }
+ return ref MemoryMarshal.GetArrayDataReference(array);
+ }
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs
deleted file mode 100644
index 0b41be2390e9d..0000000000000
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop
-{
- public sealed class ArrayMarshaller : IMarshallingGenerator
- {
- private readonly IMarshallingGenerator _manualMarshallingGenerator;
- private readonly TypePositionInfo _elementInfo;
- private readonly bool _enablePinning;
-
- public ArrayMarshaller(IMarshallingGenerator manualMarshallingGenerator, TypePositionInfo elementInfo, bool enablePinning)
- {
- _manualMarshallingGenerator = manualMarshallingGenerator;
- _elementInfo = elementInfo;
- _enablePinning = enablePinning;
- }
-
- public bool IsSupported(TargetFramework target, Version version)
- {
- return target is TargetFramework.Net && version.Major >= 7;
- }
-
- public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context)
- {
- if (IsPinningPathSupported(info, context))
- {
- if (AsNativeType(info) is PointerTypeSyntax pointerType
- && pointerType.ElementType is PredefinedTypeSyntax predefinedType
- && predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword))
- {
- return ValueBoundaryBehavior.NativeIdentifier;
- }
-
- // Cast to native type if it is not void*
- return ValueBoundaryBehavior.CastNativeIdentifier;
- }
- return _manualMarshallingGenerator.GetValueBoundaryBehavior(info, context);
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _manualMarshallingGenerator.AsNativeType(info);
- }
-
- public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info)
- {
- return _manualMarshallingGenerator.GetNativeSignatureBehavior(info);
- }
-
- public IEnumerable Generate(TypePositionInfo info, StubCodeContext context)
- {
- if (IsPinningPathSupported(info, context))
- {
- return GeneratePinningPath(info, context);
- }
- return _manualMarshallingGenerator.Generate(info, context);
- }
-
- public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context)
- {
- if (context.SingleFrameSpansNativeContext && _enablePinning)
- {
- // Only report no support for by-value contents when element is strictly blittable, such that
- // the status remains the same regardless of whether or not runtime marshalling is enabled
- if (_elementInfo.MarshallingAttributeInfo is NoMarshallingInfo
- || _elementInfo.MarshallingAttributeInfo is UnmanagedBlittableMarshallingInfo { IsStrictlyBlittable: true }
- || _elementInfo.MarshallingAttributeInfo is NativeMarshallingAttributeInfo_V1 { IsStrictlyBlittable: true })
- {
- return false;
- }
- }
- return marshalKind.HasFlag(ByValueContentsMarshalKind.Out);
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- if (IsPinningPathSupported(info, context))
- {
- return false;
- }
- return _manualMarshallingGenerator.UsesNativeIdentifier(info, context);
- }
-
- private bool IsPinningPathSupported(TypePositionInfo info, StubCodeContext context)
- {
- return context.SingleFrameSpansNativeContext && _enablePinning && !info.IsByRef && !info.IsManagedReturnPosition;
- }
-
- private IEnumerable GeneratePinningPath(TypePositionInfo info, StubCodeContext context)
- {
- (string managedIdentifer, string nativeIdentifier) = context.GetIdentifiers(info);
- string byRefIdentifier = $"__byref_{managedIdentifer}";
-
- // The element type here is used only for refs/pointers. In the pointer array case, we use byte as the basic placeholder type,
- // since we can't use pointer types in generic type parameters.
- bool isPointerArray = info.ManagedType is SzArrayType arrayType && arrayType.ElementTypeInfo is PointerTypeInfo;
- TypeSyntax arrayElementType = isPointerArray ? PredefinedType(Token(SyntaxKind.ByteKeyword)) : _elementInfo.ManagedType.Syntax;
- if (context.CurrentStage == StubCodeContext.Stage.Marshal)
- {
- // [COMPAT] We use explicit byref calculations here instead of just using a fixed statement
- // since a fixed statement converts a zero-length array to a null pointer.
- // Many native APIs, such as GDI+, ICU, etc. validate that an array parameter is non-null
- // even when the passed in array length is zero. To avoid breaking customers that want to move
- // to source-generated interop in subtle ways, we explicitly pass a reference to the 0-th element
- // of an array as long as it is non-null, matching the behavior of the built-in interop system
- // for single-dimensional zero-based arrays.
-
- // ref = ref == null ? ref *(*)0 : ref MemoryMarshal.GetArrayDataReference();
- PrefixUnaryExpressionSyntax nullRef =
- PrefixUnaryExpression(SyntaxKind.PointerIndirectionExpression,
- CastExpression(
- PointerType(arrayElementType),
- LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))));
-
- InvocationExpressionSyntax getArrayDataReference =
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- IdentifierName("GetArrayDataReference")),
- ArgumentList(SingletonSeparatedList(
- Argument(IdentifierName(managedIdentifer)))));
-
- yield return LocalDeclarationStatement(
- VariableDeclaration(
- RefType(arrayElementType))
- .WithVariables(SingletonSeparatedList(
- VariableDeclarator(Identifier(byRefIdentifier))
- .WithInitializer(EqualsValueClause(
- RefExpression(ParenthesizedExpression(
- ConditionalExpression(
- BinaryExpression(
- SyntaxKind.EqualsExpression,
- IdentifierName(managedIdentifer),
- LiteralExpression(
- SyntaxKind.NullLiteralExpression)),
- RefExpression(nullRef),
- RefExpression(getArrayDataReference)))))))));
- }
- if (context.CurrentStage == StubCodeContext.Stage.Pin)
- {
- // fixed (void* = &)
- yield return FixedStatement(
- VariableDeclaration(
- PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))),
- SingletonSeparatedList(
- VariableDeclarator(Identifier(nativeIdentifier))
- .WithInitializer(EqualsValueClause(
- PrefixUnaryExpression(SyntaxKind.AddressOfExpression, IdentifierName(byRefIdentifier)))))),
- EmptyStatement());
- }
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
index a8b4eb3a788fc..100d756bc32e5 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
@@ -299,16 +299,15 @@ private IMarshallingGenerator CreateNativeCollectionMarshaller(
// Insert the unmanaged element type into the marshaller type
TypeSyntax unmanagedElementType = elementMarshaller.AsNativeType(elementInfo).GetCompatibleGenericTypeParameterSyntax();
TypeSyntax marshallerTypeSyntax = marshallerData.MarshallerType.Syntax;
- marshallerTypeSyntax = marshallerTypeSyntax.ReplaceNodes(
- marshallerTypeSyntax.DescendantNodesAndSelf().OfType().Where(t => t.IsEquivalentTo(marshalInfo.PlaceholderTypeParameter.Syntax)),
- (_, _) => unmanagedElementType);
+ marshallerTypeSyntax = ReplacePlaceholderSyntaxWithUnmanagedTypeSyntax(marshallerTypeSyntax, marshalInfo, unmanagedElementType);
+ TypeSyntax nativeTypeSyntax = ReplacePlaceholderSyntaxWithUnmanagedTypeSyntax(marshallerData.NativeType.Syntax, marshalInfo, unmanagedElementType);
ICustomTypeMarshallingStrategy marshallingStrategy;
bool elementIsBlittable = elementMarshaller is BlittableMarshaller;
if (marshallerData.HasState)
{
- marshallingStrategy = new StatefulValueMarshalling(marshallerTypeSyntax, marshallerData.NativeType.Syntax, marshallerData.Shape);
+ marshallingStrategy = new StatefulValueMarshalling(marshallerTypeSyntax, nativeTypeSyntax, marshallerData.Shape);
if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer))
{
// Check if the buffer element type is actually the unmanaged element type
@@ -331,39 +330,51 @@ private IMarshallingGenerator CreateNativeCollectionMarshaller(
{
if (elementIsBlittable)
{
- marshallingStrategy = new StatelessLinearCollectionBlittableElementsMarshalling(marshallerTypeSyntax, marshallerData.NativeType.Syntax, marshallerData.Shape, marshallerData.CollectionElementType.Syntax, unmanagedElementType, numElementsExpression);
+ marshallingStrategy = new StatelessLinearCollectionBlittableElementsMarshalling(marshallerTypeSyntax, nativeTypeSyntax, marshallerData.Shape, marshallerData.CollectionElementType.Syntax, unmanagedElementType, numElementsExpression);
}
else
{
- marshallingStrategy = new StatelessLinearCollectionNonBlittableElementsMarshalling(marshallerTypeSyntax, marshallerData.NativeType.Syntax, marshallerData.Shape, unmanagedElementType, elementMarshaller, elementInfo, numElementsExpression);
+ marshallingStrategy = new StatelessLinearCollectionNonBlittableElementsMarshalling(marshallerTypeSyntax, nativeTypeSyntax, marshallerData.Shape, unmanagedElementType, elementMarshaller, elementInfo, numElementsExpression);
}
if (marshallerData.Shape.HasFlag(MarshallerShape.Free))
marshallingStrategy = new StatelessFreeMarshalling(marshallingStrategy, marshallerTypeSyntax);
}
+ IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(
+ marshallingStrategy,
+ enableByValueContentsMarshalling: info.ManagedType is SzArrayType && (!elementIsBlittable || ElementTypeIsSometimesNonBlittable(elementInfo)));
- if (marshalInfo.UseDefaultMarshalling && info.ManagedType is SzArrayType)
- {
- return new ArrayMarshaller(
- new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: true),
- elementInfo,
- elementIsBlittable);
- }
-
- IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false);
-
- if (marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference))
+ // Elements in the collection must be blittable to use the pinnable marshaller.
+ if (marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference) && elementIsBlittable)
{
marshallingGenerator = new StaticPinnableManagedValueMarshaller(marshallingGenerator, marshallerTypeSyntax);
}
- // Elements in the collection must be blittable to use the pinnable marshaller.
return marshalInfo.IsPinnableManagedType && elementIsBlittable
? new PinnableManagedValueMarshaller(marshallingGenerator)
- : marshallingGenerator;
+ : marshallingGenerator;
}
+ private static bool ElementTypeIsSometimesNonBlittable(TypePositionInfo elementInfo)
+ {
+ if (elementInfo.MarshallingAttributeInfo is NoMarshallingInfo
+ || elementInfo.MarshallingAttributeInfo is UnmanagedBlittableMarshallingInfo { IsStrictlyBlittable: true }
+ || elementInfo.MarshallingAttributeInfo is NativeMarshallingAttributeInfo_V1 { IsStrictlyBlittable: true })
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private static TypeSyntax ReplacePlaceholderSyntaxWithUnmanagedTypeSyntax(
+ TypeSyntax originalTypeSyntax,
+ NativeLinearCollectionMarshallingInfo marshalInfo,
+ TypeSyntax unmanagedElementType)
+ => originalTypeSyntax.ReplaceNodes(
+ originalTypeSyntax.DescendantNodesAndSelf().OfType().Where(t => t.IsEquivalentTo(marshalInfo.PlaceholderTypeParameter.Syntax)),
+ (_, _) => unmanagedElementType);
+
private void ValidateCustomNativeTypeMarshallingSupported(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo)
{
// Marshalling out or return parameter, but no out marshaller is specified
@@ -550,14 +561,6 @@ private IMarshallingGenerator CreateNativeCollectionMarshaller_V1(
marshallingStrategy,
SizeOfExpression(nativeElementType));
- if (collectionInfo.UseDefaultMarshalling && info.ManagedType is SzArrayType)
- {
- return new ArrayMarshaller(
- new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: true),
- elementInfo,
- elementIsBlittable);
- }
-
IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false);
// Elements in the collection must be blittable to use the pinnable marshaller.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs
index ffba0c05600f9..26886adb90c01 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs
@@ -117,14 +117,21 @@ private static bool TryRehydrateMarshalAsAttribute(TypePositionInfo info, out At
{
CountInfo countInfo;
MarshallingInfo elementMarshallingInfo;
- if (info.MarshallingAttributeInfo is NativeLinearCollectionMarshallingInfo_V1 collectionMarshalling
- && collectionMarshalling.UseDefaultMarshalling
- && collectionMarshalling.ElementCountInfo is NoCountInfo or SizeAndParamIndexInfo
- && collectionMarshalling.ElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler }
- )
+ if (info.MarshallingAttributeInfo is NativeLinearCollectionMarshallingInfo collectionMarshalling
+ && collectionMarshalling.ElementCountInfo is NoCountInfo or SizeAndParamIndexInfo)
{
- countInfo = collectionMarshalling.ElementCountInfo;
- elementMarshallingInfo = collectionMarshalling.ElementMarshallingInfo;
+ CustomTypeMarshallerData defaultMarshallerData = collectionMarshalling.Marshallers.GetModeOrDefault(MarshalMode.Default);
+ if ((defaultMarshallerData.MarshallerType.FullTypeName.StartsWith($"{TypeNames.System_Runtime_InteropServices_ArrayMarshaller}<")
+ || defaultMarshallerData.MarshallerType.FullTypeName.StartsWith($"{TypeNames.System_Runtime_InteropServices_PointerArrayMarshaller}<"))
+ && defaultMarshallerData.CollectionElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler })
+ {
+ countInfo = collectionMarshalling.ElementCountInfo;
+ elementMarshallingInfo = defaultMarshallerData.CollectionElementMarshallingInfo;
+ }
+ else
+ {
+ return false;
+ }
}
else if (info.MarshallingAttributeInfo is MissingSupportCollectionMarshallingInfo missingSupport)
{
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs
index b5cff6dca7684..e36892f9eb485 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs
@@ -575,7 +575,7 @@ public StatefulLinearCollectionNonBlittableElementsMarshalling(
public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context)
{
- if (!_shape.HasFlag(MarshallerShape.ToUnmanaged))
+ if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer))
yield break;
foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context))
@@ -602,9 +602,6 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i
public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
{
- if (!_shape.HasFlag(MarshallerShape.ToManaged))
- yield break;
-
string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);
if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
@@ -622,6 +619,11 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo
IdentifierName("Length")))))));
yield return GenerateByValueOutUnmarshalStatement(info, context);
}
+
+ if (!_shape.HasFlag(MarshallerShape.ToManaged))
+ {
+ yield break;
+ }
else
{
// int = ;
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs
index 59752b863f231..da467f8a0ee2f 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs
@@ -59,7 +59,7 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo
public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context)
{
- if (!_shape.HasFlag(MarshallerShape.ToUnmanaged))
+ if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer))
yield break;
(string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);
@@ -610,9 +610,6 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf
public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
{
- if (!_shape.HasFlag(MarshallerShape.ToManaged))
- yield break;
-
(string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);
string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);
@@ -629,6 +626,11 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo
IdentifierName("Length"))));
yield return GenerateByValueOutUnmarshalStatement(info, context);
}
+
+ if (!_shape.HasFlag(MarshallerShape.ToManaged))
+ {
+ yield break;
+ }
else
{
// = ;
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
index 84d5720cc3d8f..62977de2de3e4 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
@@ -151,8 +151,7 @@ public sealed record NativeLinearCollectionMarshallingInfo(
CustomTypeMarshallers Marshallers,
bool IsPinnableManagedType,
CountInfo ElementCountInfo,
- ManagedTypeInfo PlaceholderTypeParameter,
- bool UseDefaultMarshalling) : NativeMarshallingAttributeInfo(
+ ManagedTypeInfo PlaceholderTypeParameter) : NativeMarshallingAttributeInfo(
EntryPointType,
Marshallers,
IsPinnableManagedType);
@@ -166,7 +165,6 @@ public record NativeMarshallingAttributeInfo_V1(
CustomTypeMarshallerDirection Direction,
CustomTypeMarshallerFeatures MarshallingFeatures,
CustomTypeMarshallerPinning PinningFeatures,
- bool UseDefaultMarshalling,
bool IsStrictlyBlittable,
ManagedTypeInfo? BufferElementType,
int? BufferSize) : MarshallingInfo;
@@ -186,7 +184,6 @@ public sealed record NativeLinearCollectionMarshallingInfo_V1(
CustomTypeMarshallerDirection Direction,
CustomTypeMarshallerFeatures MarshallingFeatures,
CustomTypeMarshallerPinning PinningFeatures,
- bool UseDefaultMarshalling,
int? BufferSize,
CountInfo ElementCountInfo,
ManagedTypeInfo ElementType,
@@ -196,7 +193,6 @@ public sealed record NativeLinearCollectionMarshallingInfo_V1(
Direction,
MarshallingFeatures,
PinningFeatures,
- UseDefaultMarshalling,
IsStrictlyBlittable: false,
SpecialTypeInfo.Byte,
BufferSize
@@ -651,8 +647,7 @@ private MarshallingInfo CreateNativeMarshallingInfo(
marshallers.Value,
isPinnableManagedType,
parsedCountInfo,
- ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType.TypeParameters.Last()),
- UseDefaultMarshalling: !isMarshalUsingAttribute);
+ ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType.TypeParameters.Last()));
}
}
else
@@ -728,7 +723,6 @@ private MarshallingInfo CreateNativeMarshallingInfo_V1(
customTypeMarshallerData.Value.Direction,
customTypeMarshallerData.Value.Features,
pinning,
- UseDefaultMarshalling: !isMarshalUsingAttribute,
customTypeMarshallerData.Value.BufferSize,
parsedCountInfo,
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType),
@@ -740,8 +734,7 @@ private MarshallingInfo CreateNativeMarshallingInfo_V1(
nativeType,
attrData,
customTypeMarshallerData.Value,
- allowPinningManagedType: !isMarshalUsingAttribute,
- useDefaultMarshalling: !isMarshalUsingAttribute);
+ allowPinningManagedType: !isMarshalUsingAttribute);
}
private MarshallingInfo CreateNativeMarshallingInfoForValue_V1(
@@ -749,8 +742,7 @@ private MarshallingInfo CreateNativeMarshallingInfoForValue_V1(
INamedTypeSymbol nativeType,
AttributeData attrData,
CustomTypeMarshallerData_V1 customTypeMarshallerData,
- bool allowPinningManagedType,
- bool useDefaultMarshalling)
+ bool allowPinningManagedType)
{
ManagedTypeInfo? bufferElementTypeInfo = null;
if (customTypeMarshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.CallerAllocatedBuffer))
@@ -790,7 +782,6 @@ private MarshallingInfo CreateNativeMarshallingInfoForValue_V1(
customTypeMarshallerData.Direction,
customTypeMarshallerData.Features,
pinning,
- useDefaultMarshalling,
nativeType.IsStrictlyBlittable(),
bufferElementTypeInfo,
customTypeMarshallerData.BufferSize);
@@ -938,8 +929,7 @@ private MarshallingInfo CreateArrayMarshallingInfo(
marshallers.Value,
IsPinnableManagedType: false,
countInfo,
- ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller.TypeParameters.Last()),
- UseDefaultMarshalling: true);
+ ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller.TypeParameters.Last()));
}
}
else
@@ -965,7 +955,6 @@ private MarshallingInfo CreateArrayMarshallingInfo(
Direction: customTypeMarshallerData.Value.Direction,
MarshallingFeatures: customTypeMarshallerData.Value.Features,
PinningFeatures: CustomTypeMarshallerPinning.NativeType,
- UseDefaultMarshalling: true,
customTypeMarshallerData.Value.BufferSize,
ElementCountInfo: countInfo,
ElementType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType),
@@ -1018,8 +1007,7 @@ private MarshallingInfo CreateStringMarshallingInfo(
stringMarshaller,
null,
customTypeMarshallerData.Value,
- allowPinningManagedType: marshallerName is TypeNames.Utf16StringMarshaller,
- useDefaultMarshalling: false);
+ allowPinningManagedType: marshallerName is TypeNames.Utf16StringMarshaller);
}
private MarshallingInfo GetBlittableMarshallingInfo(ITypeSymbol type)
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
index f0a96eb7c4987..6edf393c32e81 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
@@ -58,9 +58,13 @@ public static string MarshalEx(InteropGenerationOptions options)
public const string System_Runtime_InteropServices_MemoryMarshal = "System.Runtime.InteropServices.MemoryMarshal";
- public const string System_Runtime_InteropServices_ArrayMarshaller_Metadata = "System.Runtime.InteropServices.Marshalling.ArrayMarshaller`1";
+ public const string System_Runtime_InteropServices_ArrayMarshaller_Metadata = "System.Runtime.InteropServices.Marshalling.ArrayMarshaller`2";
- public const string System_Runtime_InteropServices_PointerArrayMarshaller_Metadata = "System.Runtime.InteropServices.Marshalling.PointerArrayMarshaller`1";
+ public const string System_Runtime_InteropServices_PointerArrayMarshaller_Metadata = "System.Runtime.InteropServices.Marshalling.PointerArrayMarshaller`2";
+
+ public const string System_Runtime_InteropServices_ArrayMarshaller = "System.Runtime.InteropServices.Marshalling.ArrayMarshaller";
+
+ public const string System_Runtime_InteropServices_PointerArrayMarshaller = "System.Runtime.InteropServices.Marshalling.PointerArrayMarshaller";
public const string System_Runtime_InteropServices_SafeHandle = "System.Runtime.InteropServices.SafeHandle";
diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
index 8021a9d5f09d3..940490d75dc28 100644
--- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
+++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
@@ -2145,26 +2145,39 @@ public ref struct ManagedToUnmanagedIn
public void Free() { throw null; }
}
}
- [System.CLSCompliantAttribute(false)]
- [System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerAttribute(typeof(System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerAttribute.GenericPlaceholder[]),
- System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
- Features = System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures.UnmanagedResources
- | System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
- | System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures.TwoStageMarshalling)]
- public unsafe ref struct ArrayMarshaller
- {
- public ArrayMarshaller(int sizeOfNativeElement) { }
- public ArrayMarshaller(T[]? array, int sizeOfNativeElement) { }
- public ArrayMarshaller(T[]? array, System.Span buffer, int sizeOfNativeElement) { }
- public System.ReadOnlySpan GetManagedValuesSource() { throw null; }
- public System.Span GetManagedValuesDestination(int length) { throw null; }
- public System.ReadOnlySpan GetNativeValuesSource(int length) { throw null; }
- public System.Span GetNativeValuesDestination() { throw null; }
- public ref byte GetPinnableReference() { throw null; }
- public byte* ToNativeValue() { throw null; }
- public void FromNativeValue(byte* value) { }
- public T[]? ToManaged() { throw null; }
- public void FreeNative() { }
+
+ [System.CLSCompliant(false)]
+ [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder[]),
+ System.Runtime.InteropServices.Marshalling.MarshalMode.Default,
+ typeof(System.Runtime.InteropServices.Marshalling.ArrayMarshaller<,>))]
+ [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder[]),
+ System.Runtime.InteropServices.Marshalling.MarshalMode.ManagedToUnmanagedIn,
+ typeof(System.Runtime.InteropServices.Marshalling.ArrayMarshaller<,>.ManagedToUnmanagedIn))]
+ [System.Runtime.InteropServices.Marshalling.ContiguousCollectionMarshaller]
+ public static unsafe class ArrayMarshaller
+ where TUnmanagedElement : unmanaged
+ {
+ public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[]? managed, out int numElements) { throw null; }
+ public static System.ReadOnlySpan GetManagedValuesSource(T[]? managed) { throw null; }
+ public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) { throw null; }
+ public static T[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) { throw null; }
+ public static System.Span GetManagedValuesDestination(T[]? managed) { throw null; }
+ public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements) { throw null; }
+ public static void Free(TUnmanagedElement* unmanaged) { }
+
+ public unsafe ref struct ManagedToUnmanagedIn
+ {
+ private object _dummy;
+ private int _dummyPrimitive;
+ public static int BufferSize { get { throw null; } }
+ public void FromManaged(T[]? array, System.Span buffer) { }
+ public System.ReadOnlySpan GetManagedValuesSource() { throw null; }
+ public System.Span GetUnmanagedValuesDestination() { throw null; }
+ public ref TUnmanagedElement GetPinnableReference() { throw null; }
+ public static ref T GetPinnableReference(T[]? array) { throw null; }
+ public TUnmanagedElement* ToUnmanaged() { throw null; }
+ public void Free() { }
+ }
}
[System.CLSCompliant(false)]
[System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(string),
@@ -2187,6 +2200,12 @@ public ref struct ManagedToUnmanagedIn
public void Free() { throw null; }
}
}
+
+ [System.AttributeUsageAttribute(System.AttributeTargets.Struct | System.AttributeTargets.Class)]
+ public sealed partial class ContiguousCollectionMarshallerAttribute : System.Attribute
+ {
+ }
+
[System.AttributeUsageAttribute(System.AttributeTargets.Struct | System.AttributeTargets.Class, AllowMultiple = true)]
public sealed partial class CustomMarshallerAttribute : System.Attribute
{
@@ -2264,26 +2283,39 @@ public sealed partial class NativeMarshallingAttribute : System.Attribute
public NativeMarshallingAttribute(System.Type nativeType) { }
public System.Type NativeType { get { throw null; } }
}
- [System.CLSCompliantAttribute(false)]
- [System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerAttribute(typeof(System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerAttribute.GenericPlaceholder*[]),
- System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
- Features = System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures.UnmanagedResources
- | System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures.CallerAllocatedBuffer
- | System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures.TwoStageMarshalling)]
- public unsafe ref struct PointerArrayMarshaller where T : unmanaged
- {
- public PointerArrayMarshaller(int sizeOfNativeElement) { }
- public PointerArrayMarshaller(T*[]? array, int sizeOfNativeElement) { }
- public PointerArrayMarshaller(T*[]? array, System.Span buffer, int sizeOfNativeElement) { }
- public System.ReadOnlySpan GetManagedValuesSource() { throw null; }
- public System.Span GetManagedValuesDestination(int length) { throw null; }
- public System.ReadOnlySpan GetNativeValuesSource(int length) { throw null; }
- public System.Span GetNativeValuesDestination() { throw null; }
- public ref byte GetPinnableReference() { throw null; }
- public byte* ToNativeValue() { throw null; }
- public void FromNativeValue(byte* value) { }
- public T*[]? ToManaged() { throw null; }
- public void FreeNative() { }
+ [System.CLSCompliant(false)]
+ [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]),
+ System.Runtime.InteropServices.Marshalling.MarshalMode.Default,
+ typeof(System.Runtime.InteropServices.Marshalling.PointerArrayMarshaller<,>))]
+ [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]),
+ System.Runtime.InteropServices.Marshalling.MarshalMode.ManagedToUnmanagedIn,
+ typeof(System.Runtime.InteropServices.Marshalling.PointerArrayMarshaller<,>.ManagedToUnmanagedIn))]
+ [System.Runtime.InteropServices.Marshalling.ContiguousCollectionMarshaller]
+ public static unsafe class PointerArrayMarshaller
+ where T : unmanaged
+ where TUnmanagedElement : unmanaged
+ {
+ public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T*[]? managed, out int numElements) { throw null; }
+ public static System.ReadOnlySpan GetManagedValuesSource(T*[]? managed) { throw null; }
+ public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) { throw null; }
+ public static T*[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) { throw null; }
+ public static System.Span GetManagedValuesDestination(T*[]? managed) { throw null; }
+ public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements) { throw null; }
+ public static void Free(TUnmanagedElement* unmanaged) { }
+
+ public unsafe ref struct ManagedToUnmanagedIn
+ {
+ private object _dummy;
+ private int _dummyPrimitive;
+ public static int BufferSize { get { throw null; } }
+ public void FromManaged(T*[]? array, System.Span buffer) { }
+ public System.ReadOnlySpan GetManagedValuesSource() { throw null; }
+ public System.Span GetUnmanagedValuesDestination() { throw null; }
+ public ref TUnmanagedElement GetPinnableReference() { throw null; }
+ public static ref byte GetPinnableReference(T*[]? array) { throw null; }
+ public TUnmanagedElement* ToUnmanaged() { throw null; }
+ public void Free() { }
+ }
}
[System.CLSCompliant(false)]
[System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(string),