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

Downgrade arity error to warning in some cases for ContiguousCollectionMarshaller #96801

Open
ThadHouse opened this issue Jan 10, 2024 · 1 comment
Labels
area-System.Runtime.InteropServices code-analyzer Marks an issue that suggests a Roslyn analyzer
Milestone

Comments

@ThadHouse
Copy link
Contributor

ThadHouse commented Jan 10, 2024

I wanted to write a custom string marshaller that was generic across multiple of our libraries. They all have their own free() functions, so I wanted to inject a type to allow me to pass extra data to the marshaller.

[CustomMarshaller(typeof(string), MarshalMode.ManagedToUnmanagedOut, typeof(LengthStringMarshaller<,>))]
[ContiguousCollectionMarshaller]
public static unsafe class LengthStringMarshaller<TFree, TUnmanagedElement> where TUnmanagedElement : unmanaged
                                                                            where TFree : ILengthStringFree<TUnmanagedElement>
{
    public static string AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
    {
        if (unmanaged is null)
            return "";

        if (typeof(TUnmanagedElement) != typeof(byte))
        {
            throw new InvalidOperationException("TUnmanagedElement must be byte");
        }

        string ret = Encoding.UTF8.GetString((byte*)unmanaged, numElements);
        TFree.FreeString(unmanaged, numElements);
        return ret;
    }
   ...
}

I don't control either managed (string) or unmanaged (byte), so I can't attach the free function to either of those types using static interfaces. But this doesn't work, because the marshaller expects the generic arity to be N + 1 exactly. It expects that because NativeMarshallingAttribute requires N + 1

Talking to @jkoritzinsky, this could be a case where we could downgrade that error to a warning assuming the managed type is non generic, and again downgrade from warning to nothing if the managed type is defined in another assembly.

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jan 10, 2024
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jan 10, 2024
@vcsjones vcsjones added area-System.Runtime.InteropServices and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jan 10, 2024
@ghost
Copy link

ghost commented Jan 10, 2024

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

Issue Details

I wanted to write a custom string marshaller that was generic across multiple of our libraries. They all have their own free() functions, so I wanted to inject a type to allow me to pass extra data to the marshaller.

[CustomMarshaller(typeof(string), MarshalMode.ManagedToUnmanagedOut, typeof(LengthStringMarshaller<,>))]
[ContiguousCollectionMarshaller]
public static unsafe class LengthStringMarshaller<TFree, TUnmanagedElement> where TUnmanagedElement : unmanaged
                                                                            where TFree : ILengthStringFree<TUnmanagedElement>
{
    public static string AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
    {
        if (unmanaged is null)
            return "";

        if (typeof(TUnmanagedElement) != typeof(byte))
        {
            throw new InvalidOperationException("TUnmanagedElement must be byte");
        }

        string ret = Encoding.UTF8.GetString((byte*)unmanaged, numElements);
        TFree.FreeString(unmanaged, numElements);
        return ret;
    }
   ...
}

I don't control either managed (string) or unmanaged (byte), so I can't attach the free function to either of those types using static interfaces. But this doesn't work, because the marshaller expects the generic arity to be N + 1 exactly. It expects that because NativeMarshallingAttribute requires N + 1

Talking to @jkoritzinsky, this could be a case where we could downgrade that error to a warning assuming the managed type is non generic, and again downgrade from warning to nothing if the managed type is defined in another assembly.

Author: ThadHouse
Assignees: -
Labels:

area-System.Runtime.InteropServices, untriaged

Milestone: -

@AaronRobinsonMSFT AaronRobinsonMSFT added code-analyzer Marks an issue that suggests a Roslyn analyzer and removed untriaged New issue has not been triaged by the area owner labels Jan 10, 2024
@AaronRobinsonMSFT AaronRobinsonMSFT added this to the Future milestone Jan 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Runtime.InteropServices code-analyzer Marks an issue that suggests a Roslyn analyzer
Projects
Status: No status
Development

No branches or pull requests

3 participants