镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Marshal.GetDelegateForFunction feature parity request #13197

Closed

Description

@migueldeicaza

Hello team,

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.

Activity

  1. jkoritzinsky commented on Aug 1, 2019

    @jkoritzinsky
    Member
  2. AaronRobinsonMSFT commented on Aug 1, 2019

    @AaronRobinsonMSFT
    Member

    @migueldeicaza To confirm, an example of the scenario in question would be:

    class Dispatch<T>
    {
        private readonly Action<T> act;
        public Dispatch(IntPtr fptr)
        {
            this.act = Marshal.GetDelegateForFunctionPointer<Action<T>>(fptr);
        }
        public void Exec(T t)
        {
            this.act(t);
        }
    }
    
    new Dispatch<int>(...).Exec(5);

    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?

  3. jkotas commented on Aug 1, 2019

    @jkotas
    Member

    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.GetDelegateForFunctionPointer may be unnecessary.

  4. migueldeicaza commented on Aug 2, 2019

    @migueldeicaza
    ContributorAuthor

    The actual use case:

    void DoStuff (Delegate d)
    {
        var x = Marshal.GetDelegateForFunctionPointer (d);
    }
    
    void method (int a, int b) {}
    
    DoStuff ((Action<int,int>) method);
    
  5. transferred this issue fromdotnet/coreclron Jan 31, 2020
  6. added this to the Future milestone on Jan 31, 2020
  7. hamarb123 commented on Jan 4, 2022

    @hamarb123
    Contributor

    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).

  8. jkotas commented on Jan 4, 2022

    @jkotas
    Member

    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.

  9. hamarb123 commented on Jan 4, 2022

    @hamarb123
    Contributor

    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?

  10. jkotas commented on Jan 4, 2022

    @jkotas
    Member

    why is Marshal.GetDelegateForFunctionPointer(IntPtr ptr, Type t) (and presumably other methods similar to this) hidden?

    These methods are not AOT friendly. They are hidden to lead people to the AOT-friendly generic equivalents.

  11. tannergooding commented on Sep 2, 2026

    @tannergooding
    Member

    @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.

  12. jkotas commented on Sep 2, 2026

    @jkotas
    Member

    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#

  13. locked and limited conversation to collaborators on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status
      No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions