Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API Proposal] Create ReadOnlySpanMarshaller<T, TUnmanaged>.ManagedToUnmanagedOut marshaller #101136

Closed
jtschuster opened this issue Apr 16, 2024 · 3 comments
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Runtime.InteropServices blocking Marks issues that we want to fast track in order to unblock other important work
Milestone

Comments

@jtschuster
Copy link
Member

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.

@jtschuster jtschuster added api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Runtime.InteropServices labels Apr 16, 2024
@jtschuster jtschuster self-assigned this Apr 16, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Apr 16, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

@jtschuster jtschuster removed the untriaged New issue has not been triaged by the area owner label Apr 16, 2024
@AaronRobinsonMSFT AaronRobinsonMSFT added api-ready-for-review API is ready for review, it is NOT ready for implementation and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation labels Apr 16, 2024
@AaronRobinsonMSFT AaronRobinsonMSFT added this to the 9.0.0 milestone Apr 16, 2024
@AaronRobinsonMSFT AaronRobinsonMSFT added the blocking Marks issues that we want to fast track in order to unblock other important work label Jun 8, 2024
@terrajobst
Copy link
Member

terrajobst commented Jun 11, 2024

Video

  • Looks good as proposed
namespace System.Runtime.InteropServices.Marshalling;

[CustomMarshaller(typeof(System.ReadOnlySpan<>), MarshalMode.ManagedToUnmanagedOut, typeof(ReadOnlySpanMarshaller<,>.ManagedToUnmanagedOut))]
public partial 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();
    }
}

@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Jun 11, 2024
@jtschuster
Copy link
Member Author

Closed via #101095

@github-actions github-actions bot locked and limited conversation to collaborators Jul 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Runtime.InteropServices blocking Marks issues that we want to fast track in order to unblock other important work
Projects
Archived in project
Development

No branches or pull requests

3 participants