You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Marshal.GetDelegateForFunctionPointer thows an exception when the provided parameter is an Action<T>. Given that the actual function signature is known, this limitation seems unnecessary.
Mono currently allows this idiom, without throwing an exception, and is very convenient, to avoid producing a bunch of delegates for every combination of parameters during interop.
Reacted by Serafina Brocious, gdkchan, Brar Piening, Maxim, Pavel, Nikita Tsukanov, Mario Emmenlauer, Hamish Arblaster, Goolaxis and Wojciech Figat
If so, this is related to not permitting generic delegate types. That behavior is unfortunately documented as such which may make changing this behavior tough. Not against the change at all, simply unsure how much passionate people are about the current semantics.
Generics are not supported in regular interop signatures accross the board. Related discussion: See #4547 or #9136.
I think it is reasonable to relax some of these limitations for blittable types. I do not think it makes sense to relax it everywhere for everything. It would be a lot of runtime complexity for limited value.
Once it is relaxed for regular DllImport and function pointers, we can then see whether we need to go further. My hypothesis is that the function pointers will quickly become the way to do interop because of they will be faster, more light-weight and avoid "collected delegate" trap. If my hypothesis is correct, fixing the limitations in Marshal.GetDelegateForFunctionPointer may be unnecessary.
This could (not sure how many people rely on this feature of mono) be a more significant problem as people will (presumably) have to / want to transition from the Mono runtime to the core runtime in the future. I think this should be prioritised for .NET 7 / 8 (whenever the transition is required, but also earlier the better).
Luckily for me though, I don't think I'm actively using my workaround anywhere at the moment (my workaround calls GetDelegateForFunctionPointerInternal (with every check except the one we're discussing here) with a fallback to the actual method for when it's fixed in the future, hopefully the internal method won't be renamed between now and then).
my workaround calls GetDelegateForFunctionPointerInternal
Calling internal runtime methods is unsupported. We reserve the right to change the internal runtime methods anytime. Also, this workaround won't behave correctly in all cases.
Calling internal runtime methods is unsupported. We reserve the right to change the internal runtime methods anytime.
Yes, I'm aware. I'm just hoping that it won't be renamed before this change hopefully happens. If it does, I'll just have to deal with it.
Also, this workaround won't behave correctly in all cases.
I'm aware of that too, (I think) I've only ever used it (in the past) for Func & Action with blittable types for all parameters - this seems like something that is likely to work, and I don't think I had any issues (except possibly when the native function expected a float, but I provided a wrapped float in a struct, but that could have even been after I changed to function pointers, or caused by something else). I'm now using autogenerated code (including non-generic delegates, I did this before code generators) that use function pointers instead.
Also, just another quick question, why is Marshal.GetDelegateForFunctionPointer(IntPtr ptr, Type t) (and presumably other methods similar to this) hidden? Is it going to be unsupported in the future?
@jkotas, @jkoritzinsky are we ever actually going to do anything here or is this just going to sit open for a few more years and with more duplicates getting closed against it?
If we do want to do something, we might just try throwing copilot at it and seeing if it can get close enough that someone on the team can finish it out.
Otherwise, it feels prudent to just close it with the reasoning that this is generally a legacy API and that function pointers + UCO are the way to handle things moving forward.
I don't expect us to invest in improving Marshal.GetDelegateForFunctionPointer. It is a problematic API for multiple reasons. Our interop best practices recommend UnmanagedCallersOnly instead.
Activity
jkoritzinsky commentedon Aug 1, 2019
cc: @AaronRobinsonMSFT
AaronRobinsonMSFT commentedon Aug 1, 2019
@migueldeicaza To confirm, an example of the scenario in question would be:
If so, this is related to not permitting generic delegate types. That behavior is unfortunately documented as such which may make changing this behavior tough. Not against the change at all, simply unsure how much passionate people are about the current semantics.
Hi @terrajobst @richlander @jkotas, how would we feel about changing the semantics of this function?
jkotas commentedon Aug 1, 2019
Generics are not supported in regular interop signatures accross the board. Related discussion: See #4547 or #9136.
I think it is reasonable to relax some of these limitations for blittable types. I do not think it makes sense to relax it everywhere for everything. It would be a lot of runtime complexity for limited value.
I would recommend to start with relaxing the limitations for arguments of regular DllImport and function pointers that are getting a first-class C# support soon (https://github.com/dotnet/csharplang/blob/master/proposals/function-pointers.md). WIP PR dotnet/coreclr#23899 has started some of this work.
Once it is relaxed for regular DllImport and function pointers, we can then see whether we need to go further. My hypothesis is that the function pointers will quickly become the way to do interop because of they will be faster, more light-weight and avoid "collected delegate" trap. If my hypothesis is correct, fixing the limitations in
Marshal.GetDelegateForFunctionPointermay be unnecessary.migueldeicaza commentedon Aug 2, 2019
The actual use case:
hamarb123 commentedon Jan 4, 2022
This could (not sure how many people rely on this feature of mono) be a more significant problem as people will (presumably) have to / want to transition from the Mono runtime to the core runtime in the future. I think this should be prioritised for .NET 7 / 8 (whenever the transition is required, but also earlier the better).
Luckily for me though, I don't think I'm actively using my workaround anywhere at the moment (my workaround calls
GetDelegateForFunctionPointerInternal(with every check except the one we're discussing here) with a fallback to the actual method for when it's fixed in the future, hopefully the internal method won't be renamed between now and then).jkotas commentedon Jan 4, 2022
Calling internal runtime methods is unsupported. We reserve the right to change the internal runtime methods anytime. Also, this workaround won't behave correctly in all cases.
hamarb123 commentedon Jan 4, 2022
Yes, I'm aware. I'm just hoping that it won't be renamed before this change hopefully happens. If it does, I'll just have to deal with it.
I'm aware of that too, (I think) I've only ever used it (in the past) for Func & Action with blittable types for all parameters - this seems like something that is likely to work, and I don't think I had any issues (except possibly when the native function expected a float, but I provided a wrapped float in a struct, but that could have even been after I changed to function pointers, or caused by something else). I'm now using autogenerated code (including non-generic delegates, I did this before code generators) that use function pointers instead.
Also, just another quick question, why is
Marshal.GetDelegateForFunctionPointer(IntPtr ptr, Type t)(and presumably other methods similar to this) hidden? Is it going to be unsupported in the future?jkotas commentedon Jan 4, 2022
These methods are not AOT friendly. They are hidden to lead people to the AOT-friendly generic equivalents.
tannergooding commentedon Sep 2, 2026
@jkotas, @jkoritzinsky are we ever actually going to do anything here or is this just going to sit open for a few more years and with more duplicates getting closed against it?
If we do want to do something, we might just try throwing copilot at it and seeing if it can get close enough that someone on the team can finish it out.
Otherwise, it feels prudent to just close it with the reasoning that this is generally a legacy API and that function pointers + UCO are the way to handle things moving forward.
jkotas commentedon Sep 2, 2026
I don't expect us to invest in improving
Marshal.GetDelegateForFunctionPointer. It is a problematic API for multiple reasons. Our interop best practices recommend UnmanagedCallersOnly instead.From https://learn.microsoft.com/en-us/dotnet/standard/native-interop/best-practices#general-guidance: DO prefer using function pointers and UnmanagedCallersOnlyAttribute as opposed to Delegate types, when passing callbacks to unmanaged functions in C#