Skip to content

Commit

Permalink
Basic support for stateless linear collection marshalling (#71473)
Browse files Browse the repository at this point in the history
Basic stateless linear collection marshalling for blittable elements

Not handled:
- caller-allocated buffer
- guaranteed unmarshal
- pinnable reference
- non-blittable element marshalling
- element scenarios on custom marshallers
  • Loading branch information
elinor-fung authored Jul 1, 2022
1 parent 6d8a6c2 commit 19811c2
Show file tree
Hide file tree
Showing 32 changed files with 1,759 additions and 454 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace System.Runtime.InteropServices.Marshalling;
- ManagedType = managedType;
- MarshallerKind = marshallerKind;
- }
-
-
- public Type ManagedType { get; }
- public CustomTypeMarshallerKind MarshallerKind { get; }
- public int BufferSize { get; set; }
Expand All @@ -51,13 +51,13 @@ namespace System.Runtime.InteropServices.Marshalling;
- {
- }
- }
-
-
- public enum CustomTypeMarshallerKind
- {
- Value,
- LinearCollection
- }
-
-
- [Flags]
- public enum CustomTypeMarshallerFeatures
- {
Expand Down Expand Up @@ -108,8 +108,8 @@ namespace System.Runtime.InteropServices.Marshalling;
+ /// </summary>
+ public int BufferSize { get; set; }
+ }
+
+
+
+
+ /// <summary>
+ /// Base class attribute for custom marshaller attributes.
+ /// </summary>
Expand All @@ -125,7 +125,7 @@ namespace System.Runtime.InteropServices.Marshalling;
+ /// </summary>
+ public sealed class GenericPlaceholder { }
+ }
+
+
+ /// <summary>
+ /// Specify marshallers used in the managed to unmanaged direction (that is, P/Invoke)
+ /// </summary>
Expand All @@ -137,23 +137,23 @@ namespace System.Runtime.InteropServices.Marshalling;
+ /// </summary>
+ /// <param name="managedType">Managed type to marshal</param>
+ public ManagedToUnmanagedMarshallersAttribute(Type managedType) { }
+
+
+ /// <summary>
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>in</c> keyword.
+ /// </summary>
+ public Type? InMarshaller { get; set; }
+
+
+ /// <summary>
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>ref</c> keyword.
+ /// </summary>
+ public Type? RefMarshaller { get; set; }
+
+
+ /// <summary>
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>out</c> keyword.
+ /// </summary>
+ public Type? OutMarshaller { get; set; }
+ }
+
+
+ /// <summary>
+ /// Specify marshallers used in the unmanaged to managed direction (that is, Reverse P/Invoke)
+ /// </summary>
Expand All @@ -165,23 +165,23 @@ namespace System.Runtime.InteropServices.Marshalling;
+ /// </summary>
+ /// <param name="managedType">Managed type to marshal</param>
+ public UnmanagedToManagedMarshallersAttribute(Type managedType) { }
+
+
+ /// <summary>
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>in</c> keyword.
+ /// </summary>
+ public Type? InMarshaller { get; set; }
+
+
+ /// <summary>
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>ref</c> keyword.
+ /// </summary>
+ public Type? RefMarshaller { get; set; }
+
+
+ /// <summary>
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>out</c> keyword.
+ /// </summary>
+ public Type? OutMarshaller { get; set; }
+ }
+
+
+ /// <summary>
+ /// Specify marshaller for array-element marshalling and default struct field marshalling.
+ /// </summary>
Expand All @@ -195,7 +195,7 @@ namespace System.Runtime.InteropServices.Marshalling;
+ /// <param name="elementMarshaller">Marshaller type to use for marshalling <paramref name="managedType"/>.</param>
+ public ElementMarshallerAttribute(Type managedType, Type elementMarshaller) { }
+ }
+
+
+ /// <summary>
+ /// Specifies that a particular generic parameter is the collection element's unmanaged type.
+ /// </summary>
Expand Down Expand Up @@ -470,10 +470,10 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
public static class ManagedToNative
{
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, out int numElements); // Can throw exceptions
public static ReadOnlySpan<TManagedElement> GetManagedValuesSource(TCollection managed); // Can throw exceptions
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative nativeValue, int numElements); // Can throw exceptions
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative unmanaged, int numElements); // Can throw exceptions
public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
Expand All @@ -495,10 +495,10 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
public static class ManagedToNative
{
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, Span<TOther> buffer, out int numElements); // Can throw exceptions
public static ReadOnlySpan<TManagedElement> GetManagedValuesSource(TCollection managed); // Can throw exceptions
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative nativeValue, int numElements); // Can throw exceptions
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative unmanaged, int numElements); // Can throw exceptions
public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
Expand All @@ -517,11 +517,11 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
{
public static class NativeToManaged
{
public static TCollection AllocateContainerForManagedElements(int length); // Can throw exceptions
public static TCollection AllocateContainerForManagedElements(TNative unmanaged, int length); // Can throw exceptions
public static Span<TManagedElement> GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative nativeValue, int numElements); // Can throw exceptions
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative unmanaged, int numElements); // Can throw exceptions
public static void Free(TNative native); // Optional. Should not throw exceptions.
}
Expand All @@ -540,11 +540,11 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
{
public static class NativeToManaged
{
public static TCollection AllocateContainerForManagedElementsGuaranteed(int length); // Should not throw exceptions other than OutOfMemoryException.
public static TCollection AllocateContainerForManagedElementsGuaranteed(TNative unmanaged, int length); // Should not throw exceptions other than OutOfMemoryException.
public static Span<TManagedElement> GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative nativeValue, int numElements); // Can throw exceptions
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative unmanaged, int numElements); // Can throw exceptions
public static void Free(TNative native); // Optional. Should not throw exceptions.
}
Expand Down Expand Up @@ -584,7 +584,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
public ReadOnlySpan<TManagedElement> GetManagedValuesSource(); // Can throw exceptions.
public Span<byte> GetNativeValuesDestination(); // Can throw exceptions.
public Span<byte> GetUnmanagedValuesDestination(); // Can throw exceptions.
public ref TIgnored GetPinnableReference(); // Optional. Can throw exceptions.
Expand Down Expand Up @@ -615,7 +615,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
public ReadOnlySpan<TManagedElement> GetManagedValuesSource(); // Can throw exceptions.
public Span<byte> GetNativeValuesDestination(); // Can throw exceptions.
public Span<byte> GetUnmanagedValuesDestination(); // Can throw exceptions.
public ref TIgnored GetPinnableReference(); // Optional. Can throw exceptions.
Expand All @@ -642,7 +642,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
public void FromUnmanaged(TNative value); // Should not throw exceptions.
public ReadOnlySpan<TUnmanagedElement> GetNativeValuesSource(int length); // Can throw exceptions.
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int length); // Can throw exceptions.
public Span<TManagedElement> GetManagedValuesDestination(int length); // Can throw exceptions.
Expand All @@ -667,7 +667,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
public void FromUnmanaged(TNative value); // Should not throw exceptions.
public ReadOnlySpan<TUnmanagedElement> GetNativeValuesSource(int length); // Can throw exceptions.
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int length); // Can throw exceptions.
public Span<TManagedElement> GetManagedValuesDestination(int length); // Can throw exceptions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public static ManagedTypeInfo CreateTypeInfoForTypeSymbol(ITypeSymbol type)
{
return new DelegateTypeInfo(typeName, diagonsticFormattedName);
}
if (type.TypeKind == TypeKind.TypeParameter)
{
return new TypeParameterTypeInfo(typeName, diagonsticFormattedName);
}
if (type.IsValueType)
{
return new ValueTypeInfo(typeName, diagonsticFormattedName, type.IsRefLikeType);
Expand Down Expand Up @@ -80,6 +84,8 @@ public sealed record SzArrayType(ManagedTypeInfo ElementTypeInfo) : ManagedTypeI

public sealed record DelegateTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName);

public sealed record TypeParameterTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName);

public sealed record ValueTypeInfo(string FullTypeName, string DiagnosticFormattedName, bool IsByRefLike) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName);

public sealed record ReferenceTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName);
Expand Down
Loading

0 comments on commit 19811c2

Please sign in to comment.