{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/13240","repository_url":"https://api.github.com/repos/dotnet/roslyn","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/13240/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/13240/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/13240/events","html_url":"https://github.com/dotnet/roslyn/issues/13240","id":171812877,"number":13240,"title":"C# should provide better interop with unmanaged function pointers.","user":{"login":"tannergooding","id":10487869,"avatar_url":"https://avatars.githubusercontent.com/u/10487869?v=3","gravatar_id":"","url":"https://api.github.com/users/tannergooding","html_url":"https://github.com/tannergooding","followers_url":"https://api.github.com/users/tannergooding/followers","following_url":"https://api.github.com/users/tannergooding/following{/other_user}","gists_url":"https://api.github.com/users/tannergooding/gists{/gist_id}","starred_url":"https://api.github.com/users/tannergooding/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tannergooding/subscriptions","organizations_url":"https://api.github.com/users/tannergooding/orgs","repos_url":"https://api.github.com/users/tannergooding/repos","events_url":"https://api.github.com/users/tannergooding/events{/privacy}","received_events_url":"https://api.github.com/users/tannergooding/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Request","name":"Feature Request","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-08-18T03:56:36Z","updated_at":"2016-09-29T10:27:38Z","closed_at":null,"body":"**Issue**\r\nC# has no mechanism for declaring unmanaged function pointers.\r\n\r\nWhile there are a couple of mechanisms designed to work with and call unmanaged function pointers, these mechanisms may:\r\n* Incur a higher level of overhead\r\n* Require caching of the managed delegate\r\n* Emit sub-optimal instructions for invoking the unmanaged function pointer\r\n* Have issues when working with other unsafe/unmanaged code\r\n\r\n**Workaround**\r\nDeclare the function pointer using `IntPtr` and then use the `Marshal.GetDelegateForFunctionPointer` method to convert to a managed `Delegate`. Such as:\r\n\r\n```C#\r\n[UnmanagedFunctionPointer(CallingConvention.StdCall)]\r\npublic delegate void _D();\r\n\r\npublic struct S\r\n{\r\n    private IntPtr pD;\r\n\r\n    public void D()\r\n    {\r\n        var funcptr = Marshal.GetDelegateForFunctionPointer<_D>(pD);\r\n        funcptr();\r\n    }\r\n}\r\n\r\npublic static class C\r\n{\r\n    [DllImport(\"SomeBinary.dll\")]\r\n    public static extern void CreateS(out S pS);\r\n}\r\n```\r\n\r\n-or-\r\n\r\nDeclare a managed delegate and rely on the marshalling behavior to convert as appropriate. Such As:\r\n\r\n```C#\r\n[UnmanagedFunctionPointer(CallingConvention.StdCall)]\r\npublic delegate void _D();\r\n\r\npublic struct S\r\n{\r\n    [MarshalAs(UnmanagedType.FunctionPtr)]\r\n    public _D D;\r\n}\r\n\r\npublic static class C\r\n{\r\n    [DllImport(\"SomeBinary.dll\")]\r\n    public static extern void CreateS(out S pS);\r\n}\r\n```\r\n\r\n**Proposal**\r\nThe C# language should be extended to support function pointers in an unsafe context. Such as:\r\n\r\n```C#\r\nunsafe public struct S\r\n{\r\n    public void (*D)();\r\n}\r\n```\r\n\r\nThe compilation should fail if `unsafe` is missing.\r\n\r\n**Advantages**\r\nThe compiler could take advantage of the fact this is an unsafe function pointer and emit the `calli` instruction when invoking.\r\n\r\nThe compiler could provide some level of type safety when invoking the function pointer (ensuring the arguments passed in match the types required).\r\n\r\nThis would allow better interop with unmanaged languages and types that use function pointers.\r\n\r\nThis would allow a user to more readily implement VTBLs for unmanaged interop when required."},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/250428976","html_url":"https://github.com/dotnet/roslyn/issues/13240#issuecomment-250428976","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/13240","id":250428976,"user":{"login":"spellizzari","id":2003422,"avatar_url":"https://avatars.githubusercontent.com/u/2003422?v=3","gravatar_id":"","url":"https://api.github.com/users/spellizzari","html_url":"https://github.com/spellizzari","followers_url":"https://api.github.com/users/spellizzari/followers","following_url":"https://api.github.com/users/spellizzari/following{/other_user}","gists_url":"https://api.github.com/users/spellizzari/gists{/gist_id}","starred_url":"https://api.github.com/users/spellizzari/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spellizzari/subscriptions","organizations_url":"https://api.github.com/users/spellizzari/orgs","repos_url":"https://api.github.com/users/spellizzari/repos","events_url":"https://api.github.com/users/spellizzari/events{/privacy}","received_events_url":"https://api.github.com/users/spellizzari/received_events","type":"User","site_admin":false},"created_at":"2016-09-29T10:27:38Z","updated_at":"2016-09-29T10:27:38Z","body":"This feature would be welcome by projects such as SharpDX that makes its own COM wrappers for lots of Windows APIs (currently it uses the `calli` instruction by patching the MSIL code of its assemblies after the compilation).\r\n\r\nWhile searching about this topic I saw a post by Eric Lippert on StackOverflow [http://stackoverflow.com/questions/36558996/how-to-implement-c-style-function-pointers-in-c-without-using-delegates](url) where he explains the difficulties of finding the right syntax.\r\n\r\nOne workaround I can think of is to make for delegates the same thing that is currently in place for `struct`s in an unsafe context: distinguish between blittable and non-blittable types.\r\n\r\nIn an unsafe context I can use `MyStruct*` for fields, parameters and local variables as long as `MyStruct` is a blittable type. If I attempt to use pointers to managed structs I get an error at compile time.\r\n\r\nMaybe the solution would be to:\r\n- allow `MyDelegate*` for fields, parameters and local variables where `MyDelegate` would be a classic delegate definition, and produce compilation errors when `MyDelegate` contains non-blittable parameters or parameters requiring marshalling.\r\n- use the existing `UnmanagedFunctionPointerAttribute` attribute to specify the calling convention directly on the delegate.\r\n- allow the method call syntax on delegate pointers like they were delegates (that is, if `myFuncPtr` is a variable of type `MyDelegate*`, where `MyDelegate` is `delegate void MyDelegate(int p1);` I should be able to write `myFuncPtr(123)`). This would allow the compiler to produce a `calli` instruction with a safely validated signature.\r\n\r\nThe main advantage of this solution is that no new syntax is needed for the language, it is only a compiler thing."}}
{"actor":{"display_login":"spellizzari"}}