-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Background and motivation
To address #96525, we can provide a marshaller for ReadOnlySpan<T>
for ManagedToUnmanagedOut
direction. We have marshallers for UnmanagedToManagedOut and ManagedToUnmanagedIn. This API wasn't created previously due to the assumption that the managed ReadOnlySpan<T>
would need to be written to in generated marshaling code, but that isn't strictly necessary for stateful marshallers. This API would allow LibraryImport
methods to return ReadOnlySpan<T>
without creating a new marshaller or specifying the marshaller type in the method definition.
API Proposal
[System.Runtime.InteropServices.Marshalling.ContiguousCollectionMarshallerAttribute]
[System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(System.ReadOnlySpan<>), System.Runtime.InteropServices.Marshalling.MarshalMode.ManagedToUnmanagedIn, typeof(System.Runtime.InteropServices.Marshalling.ReadOnlySpanMarshaller<,>.ManagedToUnmanagedIn))]
+ [System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(System.ReadOnlySpan<>), System.Runtime.InteropServices.Marshalling.MarshalMode.ManagedToUnmanagedOut, typeof(System.Runtime.InteropServices.Marshalling.ReadOnlySpanMarshaller<,>.ManagedToUnmanagedOut))]
[System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(System.ReadOnlySpan<>), System.Runtime.InteropServices.Marshalling.MarshalMode.UnmanagedToManagedOut, typeof(System.Runtime.InteropServices.Marshalling.ReadOnlySpanMarshaller<,>.UnmanagedToManagedOut))]
public static unsafe class ReadOnlySpanMarshaller<T, TUnmanagedElement> where TUnmanagedElement : unmanaged
{
+ public struct ManagedToUnmanagedOut
+ {
+ public void FromUnmanaged(TUnmanagedElement* unmanaged) { }
+ public ReadOnlySpan<T> ToManaged() { }
+ public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int numElements) { }
+ public Span<T> GetManagedValuesDestination(int numElements) { }
+ public void Free() { }
+ }
}
API Usage
The API would primarily be used in code generated by the LibraryImport generator to unmarshal a native array into a managed ReadOnlySpan<T>
when a method returns a ReadOnlySpan<T>
or has an out
parameter of type ReadOnlySpan<T>
.
[LibraryImport("DllName")]
[return: MarshalUsing(CountElementName = nameof(length))]
public static partial ReadOnlySpan<int> GetRange(int start, int end, out int length);
Alternative Designs
A workaround is to create a LibraryImport that returns another built-in collection type and create a wrapper that converts the returned collection into a ReadOnlySpan<T>
, or use hand-written marshalling for the method.
Risk
Minimal. We already provide marshallers for ReadOnlySpan<T>
to pass a parameter in, and we have marshallers for other collections to return a value from a native method, so this is not introducing a new concept.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status