Skip to content

Commit 19811c2

Browse files
authored
Basic support for stateless linear collection marshalling (dotnet#71473)
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
1 parent 6d8a6c2 commit 19811c2

32 files changed

+1759
-454
lines changed

docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ namespace System.Runtime.InteropServices.Marshalling;
4141
- ManagedType = managedType;
4242
- MarshallerKind = marshallerKind;
4343
- }
44-
-
44+
-
4545
- public Type ManagedType { get; }
4646
- public CustomTypeMarshallerKind MarshallerKind { get; }
4747
- public int BufferSize { get; set; }
@@ -51,13 +51,13 @@ namespace System.Runtime.InteropServices.Marshalling;
5151
- {
5252
- }
5353
- }
54-
-
54+
-
5555
- public enum CustomTypeMarshallerKind
5656
- {
5757
- Value,
5858
- LinearCollection
5959
- }
60-
-
60+
-
6161
- [Flags]
6262
- public enum CustomTypeMarshallerFeatures
6363
- {
@@ -108,8 +108,8 @@ namespace System.Runtime.InteropServices.Marshalling;
108108
+ /// </summary>
109109
+ public int BufferSize { get; set; }
110110
+ }
111-
+
112-
+
111+
+
112+
+
113113
+ /// <summary>
114114
+ /// Base class attribute for custom marshaller attributes.
115115
+ /// </summary>
@@ -125,7 +125,7 @@ namespace System.Runtime.InteropServices.Marshalling;
125125
+ /// </summary>
126126
+ public sealed class GenericPlaceholder { }
127127
+ }
128-
+
128+
+
129129
+ /// <summary>
130130
+ /// Specify marshallers used in the managed to unmanaged direction (that is, P/Invoke)
131131
+ /// </summary>
@@ -137,23 +137,23 @@ namespace System.Runtime.InteropServices.Marshalling;
137137
+ /// </summary>
138138
+ /// <param name="managedType">Managed type to marshal</param>
139139
+ public ManagedToUnmanagedMarshallersAttribute(Type managedType) { }
140-
+
140+
+
141141
+ /// <summary>
142142
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>in</c> keyword.
143143
+ /// </summary>
144144
+ public Type? InMarshaller { get; set; }
145-
+
145+
+
146146
+ /// <summary>
147147
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>ref</c> keyword.
148148
+ /// </summary>
149149
+ public Type? RefMarshaller { get; set; }
150-
+
150+
+
151151
+ /// <summary>
152152
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>out</c> keyword.
153153
+ /// </summary>
154154
+ public Type? OutMarshaller { get; set; }
155155
+ }
156-
+
156+
+
157157
+ /// <summary>
158158
+ /// Specify marshallers used in the unmanaged to managed direction (that is, Reverse P/Invoke)
159159
+ /// </summary>
@@ -165,23 +165,23 @@ namespace System.Runtime.InteropServices.Marshalling;
165165
+ /// </summary>
166166
+ /// <param name="managedType">Managed type to marshal</param>
167167
+ public UnmanagedToManagedMarshallersAttribute(Type managedType) { }
168-
+
168+
+
169169
+ /// <summary>
170170
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>in</c> keyword.
171171
+ /// </summary>
172172
+ public Type? InMarshaller { get; set; }
173-
+
173+
+
174174
+ /// <summary>
175175
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>ref</c> keyword.
176176
+ /// </summary>
177177
+ public Type? RefMarshaller { get; set; }
178-
+
178+
+
179179
+ /// <summary>
180180
+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the <c>out</c> keyword.
181181
+ /// </summary>
182182
+ public Type? OutMarshaller { get; set; }
183183
+ }
184-
+
184+
+
185185
+ /// <summary>
186186
+ /// Specify marshaller for array-element marshalling and default struct field marshalling.
187187
+ /// </summary>
@@ -195,7 +195,7 @@ namespace System.Runtime.InteropServices.Marshalling;
195195
+ /// <param name="elementMarshaller">Marshaller type to use for marshalling <paramref name="managedType"/>.</param>
196196
+ public ElementMarshallerAttribute(Type managedType, Type elementMarshaller) { }
197197
+ }
198-
+
198+
+
199199
+ /// <summary>
200200
+ /// Specifies that a particular generic parameter is the collection element's unmanaged type.
201201
+ /// </summary>
@@ -470,10 +470,10 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
470470
public static class ManagedToNative
471471
{
472472
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, out int numElements); // Can throw exceptions
473-
473+
474474
public static ReadOnlySpan<TManagedElement> GetManagedValuesSource(TCollection managed); // Can throw exceptions
475475
476-
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative nativeValue, int numElements); // Can throw exceptions
476+
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative unmanaged, int numElements); // Can throw exceptions
477477
478478
public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
479479
@@ -495,10 +495,10 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
495495
public static class ManagedToNative
496496
{
497497
public static TNative AllocateContainerForUnmanagedElements(TCollection managed, Span<TOther> buffer, out int numElements); // Can throw exceptions
498-
498+
499499
public static ReadOnlySpan<TManagedElement> GetManagedValuesSource(TCollection managed); // Can throw exceptions
500500
501-
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative nativeValue, int numElements); // Can throw exceptions
501+
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TNative unmanaged, int numElements); // Can throw exceptions
502502
503503
public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke.
504504
@@ -517,11 +517,11 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
517517
{
518518
public static class NativeToManaged
519519
{
520-
public static TCollection AllocateContainerForManagedElements(int length); // Can throw exceptions
520+
public static TCollection AllocateContainerForManagedElements(TNative unmanaged, int length); // Can throw exceptions
521521
522522
public static Span<TManagedElement> GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions
523523
524-
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative nativeValue, int numElements); // Can throw exceptions
524+
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative unmanaged, int numElements); // Can throw exceptions
525525
526526
public static void Free(TNative native); // Optional. Should not throw exceptions.
527527
}
@@ -540,11 +540,11 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
540540
{
541541
public static class NativeToManaged
542542
{
543-
public static TCollection AllocateContainerForManagedElementsGuaranteed(int length); // Should not throw exceptions other than OutOfMemoryException.
543+
public static TCollection AllocateContainerForManagedElementsGuaranteed(TNative unmanaged, int length); // Should not throw exceptions other than OutOfMemoryException.
544544
545545
public static Span<TManagedElement> GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions
546546
547-
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative nativeValue, int numElements); // Can throw exceptions
547+
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TNative unmanaged, int numElements); // Can throw exceptions
548548
549549
public static void Free(TNative native); // Optional. Should not throw exceptions.
550550
}
@@ -584,7 +584,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
584584
585585
public ReadOnlySpan<TManagedElement> GetManagedValuesSource(); // Can throw exceptions.
586586
587-
public Span<byte> GetNativeValuesDestination(); // Can throw exceptions.
587+
public Span<byte> GetUnmanagedValuesDestination(); // Can throw exceptions.
588588
589589
public ref TIgnored GetPinnableReference(); // Optional. Can throw exceptions.
590590
@@ -615,7 +615,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
615615
616616
public ReadOnlySpan<TManagedElement> GetManagedValuesSource(); // Can throw exceptions.
617617
618-
public Span<byte> GetNativeValuesDestination(); // Can throw exceptions.
618+
public Span<byte> GetUnmanagedValuesDestination(); // Can throw exceptions.
619619
620620
public ref TIgnored GetPinnableReference(); // Optional. Can throw exceptions.
621621
@@ -642,7 +642,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
642642
643643
public void FromUnmanaged(TNative value); // Should not throw exceptions.
644644
645-
public ReadOnlySpan<TUnmanagedElement> GetNativeValuesSource(int length); // Can throw exceptions.
645+
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int length); // Can throw exceptions.
646646
647647
public Span<TManagedElement> GetManagedValuesDestination(int length); // Can throw exceptions.
648648
@@ -667,7 +667,7 @@ static class TMarshaller<T, U, V..., [ElementUnmanagedType] TUnmanagedElement> w
667667
668668
public void FromUnmanaged(TNative value); // Should not throw exceptions.
669669
670-
public ReadOnlySpan<TUnmanagedElement> GetNativeValuesSource(int length); // Can throw exceptions.
670+
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int length); // Can throw exceptions.
671671
672672
public Span<TManagedElement> GetManagedValuesDestination(int length); // Can throw exceptions.
673673

src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public static ManagedTypeInfo CreateTypeInfoForTypeSymbol(ITypeSymbol type)
4545
{
4646
return new DelegateTypeInfo(typeName, diagonsticFormattedName);
4747
}
48+
if (type.TypeKind == TypeKind.TypeParameter)
49+
{
50+
return new TypeParameterTypeInfo(typeName, diagonsticFormattedName);
51+
}
4852
if (type.IsValueType)
4953
{
5054
return new ValueTypeInfo(typeName, diagonsticFormattedName, type.IsRefLikeType);
@@ -80,6 +84,8 @@ public sealed record SzArrayType(ManagedTypeInfo ElementTypeInfo) : ManagedTypeI
8084

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

87+
public sealed record TypeParameterTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName);
88+
8389
public sealed record ValueTypeInfo(string FullTypeName, string DiagnosticFormattedName, bool IsByRefLike) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName);
8490

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

0 commit comments

Comments
 (0)