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

Marshal.PtrToStructure<T> does not permit constructed generics #13756

Closed
Scottj1s opened this issue Nov 8, 2019 · 8 comments
Closed

Marshal.PtrToStructure<T> does not permit constructed generics #13756

Scottj1s opened this issue Nov 8, 2019 · 8 comments
Assignees
Milestone

Comments

@Scottj1s
Copy link

Scottj1s commented Nov 8, 2019

PtrToStructure does not permit a constructed generic argument for T. Attempts to use one result in an exception with the diagnostic: 'The specified Type must not be a generic type definition.' This message seems to indicate that the check in PtrToStructure for IsGenericType (which identifies both unbound and constructed types) should actually have been IsGenericTypeDefinition (which only identifies unbound types). In experiments, stepping over the IsGenericType check allows PtrToStructure to succeed, as long as T is blittable.

Note that Mono does not have this restriction:
https://github.com/mono/mono/blob/bd278dd00dd24b3e8c735a4220afa6cb3ba317ee/netcore/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Mono.cs#L311-L316 (Note specifically line 314).

@AaronRobinsonMSFT AaronRobinsonMSFT self-assigned this Nov 8, 2019
@AaronRobinsonMSFT
Copy link
Member

Related: dotnet/coreclr#23899

/cc @jkoritzinsky

@AaronRobinsonMSFT
Copy link
Member

Closing per recommended workflow described at dotnet/coreclr#27840 (comment)

@Scottj1s
Copy link
Author

With further investigation, this issue is not resolved.

Marshal.PtrToStructure actually converts unmanaged function pointers to GC'd delegates, so vtables aren't blittable and can't use casting as Jan recommends.

Further, using a formatted reference type (class with struct layout) vs a struct is not ideal, since it requires a GC allocation. It doesn't appear possible to fold that allocation into a larger object and only marshal a portion of it.

@tannergooding
Copy link
Member

You could, however, manually marshal the fields.

That is, you can define a struct IUnknownVtbl { IntPtr QueryInterface; IntPtr AddRef; IntPtr Release; }, use that for the interop case, and then call Marshal.GetDelegateForFunctionPointer on each field (and the reverse when needing to marshal).

It should provide the same functionality as what Marshal.PtrToStructure would do.

C# 9 is also (assuming it doesn't get pulled out) currently targeting the addition of function pointers, which would make the manual VTBL scenario both blittable and readily usable (without needing to create delegates).

@AaronRobinsonMSFT
Copy link
Member

@tannergooding Yes, that is an approach and will work in many cases however there are still issues in some scenarios involving generics - these are going to have to be handled one off. The function pointers work is the gold star here and hopefully that will come on line sooner rather than later.

@Scottj1s
Copy link
Author

Yes, unfortunately GetDelegateForFunctionPointer suffers from the same limitation as PtrToStructure - no support for generics. See also: https://github.com/dotnet/coreclr/issues/1685

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the 5.0 milestone Jan 31, 2020
@AaronRobinsonMSFT
Copy link
Member

@Scottj1s This is looking less likely to happen. Do you feel this is still needed for your work?

@Scottj1s
Copy link
Author

@Scottj1s This is looking less likely to happen. Do you feel this is still needed for your work?

No, not any more. I have a reasonable workaround in Expression.GetDelegateType

@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants