未验证 提交 b4dd16b4 编写于 作者: J Jeremy Koritzinsky 提交者: GitHub

Move ArrayMarshaller and PointerArrayMarshaller to the v2 design (#71978)

上级 a3a106f4
......@@ -875,6 +875,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\AnsiStringMarshaller.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\ArrayMarshaller.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\BStrStringMarshaller.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\ContiguousCollectionMarshallerAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\CustomMarshallerAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\CustomTypeMarshallerAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshalling\CustomTypeMarshallerDirection.cs" />
......
......@@ -10,52 +10,77 @@ namespace System.Runtime.InteropServices.Marshalling
/// Marshaller for arrays
/// </summary>
/// <typeparam name="T">Array element type</typeparam>
/// <typeparam name="TUnmanagedElement">The unmanaged type for the element type</typeparam>
[CLSCompliant(false)]
[CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder[]),
CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
public unsafe ref struct ArrayMarshaller<T>
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]),
MarshalMode.Default,
typeof(ArrayMarshaller<,>))]
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]),
MarshalMode.ManagedToUnmanagedIn,
typeof(ArrayMarshaller<,>.ManagedToUnmanagedIn))]
[ContiguousCollectionMarshaller]
public static unsafe class ArrayMarshaller<T, TUnmanagedElement>
where TUnmanagedElement : unmanaged
{
private readonly int _sizeOfNativeElement;
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[]? managed, out int numElements)
{
if (managed is null)
{
numElements = 0;
return null;
}
private T[]? _managedArray;
private IntPtr _allocatedMemory;
private Span<byte> _span;
numElements = managed.Length;
/// <summary>
/// Initializes a new instance of the <see cref="ArrayMarshaller{T}"/>.
/// </summary>
/// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
public ArrayMarshaller(int sizeOfNativeElement)
: this()
// Always allocate at least one byte when the array is zero-length.
int spaceToAllocate = Math.Max(checked(sizeof(TUnmanagedElement) * numElements), 1);
return (TUnmanagedElement*)Marshal.AllocCoTaskMem(spaceToAllocate);
}
public static ReadOnlySpan<T> GetManagedValuesSource(T[]? managed)
=> managed;
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
=> new Span<TUnmanagedElement>(unmanaged, numElements);
public static T[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
{
_sizeOfNativeElement = sizeOfNativeElement;
if (unmanaged is null)
return null;
return new T[numElements];
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayMarshaller{T}"/>.
/// </summary>
/// <param name="array">Array to be marshalled.</param>
/// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
public ArrayMarshaller(T[]? array, int sizeOfNativeElement)
: this(array, Span<byte>.Empty, sizeOfNativeElement)
{ }
public static Span<T> GetManagedValuesDestination(T[]? managed)
=> managed;
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements)
=> new ReadOnlySpan<TUnmanagedElement>(unmanagedValue, numElements);
public static void Free(TUnmanagedElement* unmanaged)
=> Marshal.FreeCoTaskMem((IntPtr)unmanaged);
public ref struct ManagedToUnmanagedIn
{
// 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<TUnmanagedElement> _span;
/// <summary>
/// Initializes a new instance of the <see cref="ArrayMarshaller{T}"/>.
/// Initializes the <see cref="ArrayMarshaller{T, TUnmanagedElement}.ManagedToUnmanagedIn"/> marshaller.
/// </summary>
/// <param name="array">Array to be marshalled.</param>
/// <param name="buffer">Buffer that may be used for marshalling.</param>
/// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
/// <remarks>
/// The <paramref name="buffer"/> must not be movable - that is, it should not be
/// on the managed heap or it should be pinned.
/// </remarks>
/// <seealso cref="CustomTypeMarshallerFeatures.CallerAllocatedBuffer"/>
public ArrayMarshaller(T[]? array, Span<byte> buffer, int sizeOfNativeElement)
public void FromManaged(T[]? array, Span<TUnmanagedElement> buffer)
{
_allocatedMemory = default;
_sizeOfNativeElement = sizeOfNativeElement;
_allocatedMemory = null;
if (array is null)
{
_managedArray = null;
......@@ -66,16 +91,16 @@ public ArrayMarshaller(T[]? array, Span<byte> buffer, int sizeOfNativeElement)
_managedArray = array;
// 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)
if (array.Length <= buffer.Length)
{
_span = buffer[0..spaceToAllocate];
_span = buffer[0..array.Length];
}
else
{
_allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
_span = new Span<byte>((void*)_allocatedMemory, spaceToAllocate);
int bufferSize = checked(array.Length * sizeof(TUnmanagedElement));
int spaceToAllocate = Math.Max(bufferSize, 1);
_allocatedMemory = (TUnmanagedElement*)NativeMemory.Alloc((nuint)spaceToAllocate);
_span = new Span<TUnmanagedElement>(_allocatedMemory, array.Length);
}
}
......@@ -83,74 +108,40 @@ public ArrayMarshaller(T[]? array, Span<byte> buffer, int sizeOfNativeElement)
/// Gets a span that points to the memory where the managed values of the array are stored.
/// </summary>
/// <returns>Span over managed values of the array.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.In"/>
public ReadOnlySpan<T> GetManagedValuesSource() => _managedArray;
/// <summary>
/// Gets a span that points to the memory where the unmarshalled managed values of the array should be stored.
/// </summary>
/// <param name="length">Length of the array.</param>
/// <returns>Span where managed values of the array should be stored.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.Out"/>
public Span<T> GetManagedValuesDestination(int length) => _allocatedMemory == IntPtr.Zero ? null : _managedArray = new T[length];
/// <summary>
/// Returns a span that points to the memory where the native values of the array are stored after the native call.
/// </summary>
/// <param name="length">Length of the array.</param>
/// <returns>Span over the native values of the array.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.Out"/>
public ReadOnlySpan<byte> GetNativeValuesSource(int length)
{
if (_allocatedMemory == IntPtr.Zero)
return default;
int allocatedSize = checked(length * _sizeOfNativeElement);
_span = new Span<byte>((void*)_allocatedMemory, allocatedSize);
return _span;
}
/// <summary>
/// Returns a span that points to the memory where the native values of the array should be stored.
/// Returns a span that points to the memory where the unmanaged values of the array should be stored.
/// </summary>
/// <returns>Span where native values of the array should be stored.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.In"/>
public Span<byte> GetNativeValuesDestination() => _span;
/// <returns>Span where unmanaged values of the array should be stored.</returns>
public Span<TUnmanagedElement> GetUnmanagedValuesDestination() => _span;
/// <summary>
/// Returns a reference to the marshalled array.
/// </summary>
public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
public ref TUnmanagedElement GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
/// <summary>
/// Returns the native value representing the array.
/// Returns the unmanaged value representing the array.
/// </summary>
/// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)Unsafe.AsPointer(ref GetPinnableReference());
/// <summary>
/// Sets the native value representing the array.
/// Frees resources.
/// </summary>
/// <param name="value">The native value.</param>
/// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
public void FromNativeValue(byte* value)
public void Free()
{
_allocatedMemory = (IntPtr)value;
NativeMemory.Free(_allocatedMemory);
}
/// <summary>
/// Returns the managed array.
/// </summary>
/// <seealso cref="CustomTypeMarshallerDirection.Out"/>
public T[]? ToManaged() => _managedArray;
/// <summary>
/// Frees native resources.
/// </summary>
/// <seealso cref="CustomTypeMarshallerFeatures.UnmanagedResources"/>
public void FreeNative()
public static ref T GetPinnableReference(T[]? array)
{
if (array is null)
{
Marshal.FreeCoTaskMem(_allocatedMemory);
return ref Unsafe.NullRef<T>();
}
return ref MemoryMarshal.GetArrayDataReference(array);
}
}
}
}
......@@ -10,52 +10,77 @@ namespace System.Runtime.InteropServices.Marshalling
/// Marshaller for arrays of pointers
/// </summary>
/// <typeparam name="T">Array element pointer type</typeparam>
/// <typeparam name="TUnmanagedElement">The unmanaged type for the element pointer type</typeparam>
[CLSCompliant(false)]
[CustomTypeMarshaller(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder*[]),
CustomTypeMarshallerKind.LinearCollection, BufferSize = 0x200,
Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling)]
public unsafe ref struct PointerArrayMarshaller<T> 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<T, TUnmanagedElement>
where T : unmanaged
where TUnmanagedElement : unmanaged
{
private readonly int _sizeOfNativeElement;
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T*[]? managed, out int numElements)
{
if (managed is null)
{
numElements = 0;
return null;
}
private T*[]? _managedArray;
private IntPtr _allocatedMemory;
private Span<byte> _span;
numElements = managed.Length;
/// <summary>
/// Initializes a new instance of the <see cref="PointerArrayMarshaller{T}"/>.
/// </summary>
/// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
public PointerArrayMarshaller(int sizeOfNativeElement)
: this()
// Always allocate at least one byte when the array is zero-length.
int spaceToAllocate = Math.Max(checked(sizeof(TUnmanagedElement) * numElements), 1);
return (TUnmanagedElement*)Marshal.AllocCoTaskMem(spaceToAllocate);
}
public static ReadOnlySpan<IntPtr> GetManagedValuesSource(T*[]? managed)
=> Unsafe.As<IntPtr[]>(managed);
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
=> new Span<TUnmanagedElement>(unmanaged, numElements);
public static T*[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
{
_sizeOfNativeElement = sizeOfNativeElement;
if (unmanaged is null)
return null;
return new T*[numElements];
}
/// <summary>
/// Initializes a new instance of the <see cref="PointerArrayMarshaller{T}"/>.
/// </summary>
/// <param name="array">Array to be marshalled.</param>
/// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
public PointerArrayMarshaller(T*[]? array, int sizeOfNativeElement)
: this(array, Span<byte>.Empty, sizeOfNativeElement)
{ }
public static Span<IntPtr> GetManagedValuesDestination(T*[]? managed)
=> Unsafe.As<IntPtr[]>(managed);
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements)
=> new ReadOnlySpan<TUnmanagedElement>(unmanagedValue, numElements);
public static void Free(TUnmanagedElement* unmanaged)
=> Marshal.FreeCoTaskMem((IntPtr)unmanaged);
public ref struct ManagedToUnmanagedIn
{
public static int BufferSize => 0x200 / sizeof(TUnmanagedElement);
private T*[]? _managedArray;
private TUnmanagedElement* _allocatedMemory;
private Span<TUnmanagedElement> _span;
/// <summary>
/// Initializes a new instance of the <see cref="PointerArrayMarshaller{T}"/>.
/// Initializes the <see cref="PointerArrayMarshaller{T, TUnmanagedElement}.ManagedToUnmanagedIn"/> marshaller.
/// </summary>
/// <param name="array">Array to be marshalled.</param>
/// <param name="buffer">Buffer that may be used for marshalling.</param>
/// <param name="sizeOfNativeElement">Size of the native element in bytes.</param>
/// <remarks>
/// The <paramref name="buffer"/> must not be movable - that is, it should not be
/// on the managed heap or it should be pinned.
/// </remarks>
/// <seealso cref="CustomTypeMarshallerFeatures.CallerAllocatedBuffer"/>
public PointerArrayMarshaller(T*[]? array, Span<byte> buffer, int sizeOfNativeElement)
public void FromManaged(T*[]? array, Span<TUnmanagedElement> buffer)
{
_allocatedMemory = default;
_sizeOfNativeElement = sizeOfNativeElement;
_allocatedMemory = null;
if (array is null)
{
_managedArray = null;
......@@ -66,16 +91,16 @@ public PointerArrayMarshaller(T*[]? array, Span<byte> buffer, int sizeOfNativeEl
_managedArray = array;
// 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)
if (array.Length <= buffer.Length)
{
_span = buffer[0..spaceToAllocate];
_span = buffer[0..array.Length];
}
else
{
_allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
_span = new Span<byte>((void*)_allocatedMemory, spaceToAllocate);
int bufferSize = checked(array.Length * sizeof(TUnmanagedElement));
int spaceToAllocate = Math.Max(bufferSize, 1);
_allocatedMemory = (TUnmanagedElement*)NativeMemory.Alloc((nuint)spaceToAllocate);
_span = new Span<TUnmanagedElement>(_allocatedMemory, array.Length);
}
}
......@@ -83,78 +108,40 @@ public PointerArrayMarshaller(T*[]? array, Span<byte> buffer, int sizeOfNativeEl
/// Gets a span that points to the memory where the managed values of the array are stored.
/// </summary>
/// <returns>Span over managed values of the array.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.In"/>
public ReadOnlySpan<IntPtr> GetManagedValuesSource() => Unsafe.As<IntPtr[]>(_managedArray);
/// <summary>
/// Gets a span that points to the memory where the unmarshalled managed values of the array should be stored.
/// Returns a span that points to the memory where the unmanaged values of the array should be stored.
/// </summary>
/// <param name="length">Length of the array.</param>
/// <returns>Span where managed values of the array should be stored.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.Out"/>
public Span<IntPtr> GetManagedValuesDestination(int length)
{
if (_allocatedMemory == IntPtr.Zero)
return null;
_managedArray = new T*[length];
return Unsafe.As<IntPtr[]>(_managedArray);
}
/// <summary>
/// Returns a span that points to the memory where the native values of the array are stored after the native call.
/// </summary>
/// <param name="length">Length of the array.</param>
/// <returns>Span over the native values of the array.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.Out"/>
public ReadOnlySpan<byte> GetNativeValuesSource(int length)
{
if (_allocatedMemory == IntPtr.Zero)
return default;
int allocatedSize = checked(length * _sizeOfNativeElement);
_span = new Span<byte>((void*)_allocatedMemory, allocatedSize);
return _span;
}
/// <summary>
/// Returns a span that points to the memory where the native values of the array should be stored.
/// </summary>
/// <returns>Span where native values of the array should be stored.</returns>
/// <seealso cref="CustomTypeMarshallerDirection.In"/>
public Span<byte> GetNativeValuesDestination() => _span;
/// <returns>Span where unmanaged values of the array should be stored.</returns>
public Span<TUnmanagedElement> GetUnmanagedValuesDestination() => _span;
/// <summary>
/// Returns a reference to the marshalled array.
/// </summary>
public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
/// <summary>
/// Returns the native value representing the array.
/// </summary>
/// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
public ref TUnmanagedElement GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
/// <summary>
/// Sets the native value representing the array.
/// Returns the unmanaged value representing the array.
/// </summary>
/// <param name="value">The native value.</param>
/// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/>
public void FromNativeValue(byte* value) => _allocatedMemory = (IntPtr)value;
public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)Unsafe.AsPointer(ref GetPinnableReference());
/// <summary>
/// Returns the managed array.
/// Frees resources.
/// </summary>
/// <seealso cref="CustomTypeMarshallerDirection.Out"/>
public T*[]? ToManaged() => _managedArray;
public void Free()
{
NativeMemory.Free(_allocatedMemory);
}
/// <summary>
/// Frees native resources.
/// </summary>
/// <seealso cref="CustomTypeMarshallerFeatures.UnmanagedResources"/>
public void FreeNative()
public static ref byte GetPinnableReference(T*[]? array)
{
if (array is null)
{
Marshal.FreeCoTaskMem(_allocatedMemory);
return ref Unsafe.NullRef<byte>();
}
return ref MemoryMarshal.GetArrayDataReference(array);
}
}
}
}
// 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<StatementSyntax> 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<StatementSyntax> 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 <elementType> <byRefIdentifier> = ref <managedIdentifer> == null ? ref *(<elementType>*)0 : ref MemoryMarshal.GetArrayDataReference(<managedIdentifer>);
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* <nativeIdentifier> = &<byRefIdentifier>)
yield return FixedStatement(
VariableDeclaration(
PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))),
SingletonSeparatedList(
VariableDeclarator(Identifier(nativeIdentifier))
.WithInitializer(EqualsValueClause(
PrefixUnaryExpression(SyntaxKind.AddressOfExpression, IdentifierName(byRefIdentifier)))))),
EmptyStatement());
}
}
}
}
......@@ -299,16 +299,15 @@ private IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo
// 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<TypeSyntax>().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 CreateCustomNativeTypeMarshaller(TypePositionInfo
{
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;
}
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<TypeSyntax>().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 static void ValidateCustomNativeTypeMarshallingSupported_V1(TypePosition
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.
......
......@@ -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)
{
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 = collectionMarshalling.ElementMarshallingInfo;
elementMarshallingInfo = defaultMarshallerData.CollectionElementMarshallingInfo;
}
else
{
return false;
}
}
else if (info.MarshallingAttributeInfo is MissingSupportCollectionMarshallingInfo missingSupport)
{
......
......@@ -575,7 +575,7 @@ internal sealed class StatefulLinearCollectionNonBlittableElementsMarshalling :
public IEnumerable<StatementSyntax> 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<StatementSyntax> GenerateMarshalStatements(TypePositionInfo i
public IEnumerable<StatementSyntax> 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<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo
IdentifierName("Length")))))));
yield return GenerateByValueOutUnmarshalStatement(info, context);
}
if (!_shape.HasFlag(MarshallerShape.ToManaged))
{
yield break;
}
else
{
// int <numElements> = <numElementsExpression>;
......
......@@ -59,7 +59,7 @@ public IEnumerable<StatementSyntax> GenerateGuaranteedUnmarshalStatements(TypePo
public IEnumerable<StatementSyntax> 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<StatementSyntax> GenerateSetupStatements(TypePositionInfo inf
public IEnumerable<StatementSyntax> 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<StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo
IdentifierName("Length"))));
yield return GenerateByValueOutUnmarshalStatement(info, context);
}
if (!_shape.HasFlag(MarshallerShape.ToManaged))
{
yield break;
}
else
{
// <numElements> = <numElementsExpression>;
......
......@@ -151,8 +151,7 @@ public enum CustomTypeMarshallerPinning
CustomTypeMarshallers Marshallers,
bool IsPinnableManagedType,
CountInfo ElementCountInfo,
ManagedTypeInfo PlaceholderTypeParameter,
bool UseDefaultMarshalling) : NativeMarshallingAttributeInfo(
ManagedTypeInfo PlaceholderTypeParameter) : NativeMarshallingAttributeInfo(
EntryPointType,
Marshallers,
IsPinnableManagedType);
......@@ -166,7 +165,6 @@ public enum CustomTypeMarshallerPinning
CustomTypeMarshallerDirection Direction,
CustomTypeMarshallerFeatures MarshallingFeatures,
CustomTypeMarshallerPinning PinningFeatures,
bool UseDefaultMarshalling,
bool IsStrictlyBlittable,
ManagedTypeInfo? BufferElementType,
int? BufferSize) : MarshallingInfo;
......@@ -186,7 +184,6 @@ public enum CustomTypeMarshallerPinning
CustomTypeMarshallerDirection Direction,
CustomTypeMarshallerFeatures MarshallingFeatures,
CustomTypeMarshallerPinning PinningFeatures,
bool UseDefaultMarshalling,
int? BufferSize,
CountInfo ElementCountInfo,
ManagedTypeInfo ElementType,
......@@ -196,7 +193,6 @@ public enum CustomTypeMarshallerPinning
Direction,
MarshallingFeatures,
PinningFeatures,
UseDefaultMarshalling,
IsStrictlyBlittable: false,
SpecialTypeInfo.Byte,
BufferSize
......@@ -651,8 +647,7 @@ private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
marshallers.Value,
isPinnableManagedType,
parsedCountInfo,
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType.TypeParameters.Last()),
UseDefaultMarshalling: !isMarshalUsingAttribute);
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType.TypeParameters.Last()));
}
}
else
......@@ -728,7 +723,6 @@ private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
customTypeMarshallerData.Value.Direction,
customTypeMarshallerData.Value.Features,
pinning,
UseDefaultMarshalling: !isMarshalUsingAttribute,
customTypeMarshallerData.Value.BufferSize,
parsedCountInfo,
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType),
......@@ -740,8 +734,7 @@ private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
nativeType,
attrData,
customTypeMarshallerData.Value,
allowPinningManagedType: !isMarshalUsingAttribute,
useDefaultMarshalling: !isMarshalUsingAttribute);
allowPinningManagedType: !isMarshalUsingAttribute);
}
private MarshallingInfo CreateNativeMarshallingInfoForValue_V1(
......@@ -749,8 +742,7 @@ private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
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 CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
customTypeMarshallerData.Direction,
customTypeMarshallerData.Features,
pinning,
useDefaultMarshalling,
nativeType.IsStrictlyBlittable(),
bufferElementTypeInfo,
customTypeMarshallerData.BufferSize);
......@@ -938,8 +929,7 @@ private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
marshallers.Value,
IsPinnableManagedType: false,
countInfo,
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller.TypeParameters.Last()),
UseDefaultMarshalling: true);
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller.TypeParameters.Last()));
}
}
else
......@@ -965,7 +955,6 @@ private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
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 CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashS
stringMarshaller,
null,
customTypeMarshallerData.Value,
allowPinningManagedType: marshallerName is TypeNames.Utf16StringMarshaller,
useDefaultMarshalling: false);
allowPinningManagedType: marshallerName is TypeNames.Utf16StringMarshaller);
}
private MarshallingInfo GetBlittableMarshallingInfo(ITypeSymbol type)
......
......@@ -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";
......
......@@ -2145,26 +2145,39 @@ public static unsafe class AnsiStringMarshaller
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<T>
{
public ArrayMarshaller(int sizeOfNativeElement) { }
public ArrayMarshaller(T[]? array, int sizeOfNativeElement) { }
public ArrayMarshaller(T[]? array, System.Span<byte> buffer, int sizeOfNativeElement) { }
[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<T, TUnmanagedElement>
where TUnmanagedElement : unmanaged
{
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[]? managed, out int numElements) { throw null; }
public static System.ReadOnlySpan<T> GetManagedValuesSource(T[]? managed) { throw null; }
public static System.Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) { throw null; }
public static T[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) { throw null; }
public static System.Span<T> GetManagedValuesDestination(T[]? managed) { throw null; }
public static System.ReadOnlySpan<TUnmanagedElement> 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<TUnmanagedElement> buffer) { }
public System.ReadOnlySpan<T> GetManagedValuesSource() { throw null; }
public System.Span<T> GetManagedValuesDestination(int length) { throw null; }
public System.ReadOnlySpan<byte> GetNativeValuesSource(int length) { throw null; }
public System.Span<byte> 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() { }
public System.Span<TUnmanagedElement> 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 static unsafe class BStrStringMarshaller
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<T> where T : unmanaged
{
public PointerArrayMarshaller(int sizeOfNativeElement) { }
public PointerArrayMarshaller(T*[]? array, int sizeOfNativeElement) { }
public PointerArrayMarshaller(T*[]? array, System.Span<byte> buffer, int sizeOfNativeElement) { }
[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<T, TUnmanagedElement>
where T : unmanaged
where TUnmanagedElement : unmanaged
{
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T*[]? managed, out int numElements) { throw null; }
public static System.ReadOnlySpan<IntPtr> GetManagedValuesSource(T*[]? managed) { throw null; }
public static System.Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) { throw null; }
public static T*[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) { throw null; }
public static System.Span<IntPtr> GetManagedValuesDestination(T*[]? managed) { throw null; }
public static System.ReadOnlySpan<TUnmanagedElement> 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<TUnmanagedElement> buffer) { }
public System.ReadOnlySpan<IntPtr> GetManagedValuesSource() { throw null; }
public System.Span<IntPtr> GetManagedValuesDestination(int length) { throw null; }
public System.ReadOnlySpan<byte> GetNativeValuesSource(int length) { throw null; }
public System.Span<byte> 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() { }
public System.Span<TUnmanagedElement> 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),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册