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

FuncPtr interop: support more than 16 arguments #493

Open
ForNeVeR opened this issue Nov 23, 2023 · 2 comments
Open

FuncPtr interop: support more than 16 arguments #493

ForNeVeR opened this issue Nov 23, 2023 · 2 comments
Labels
area:cil-interop Related to CIL (.NET) interop kind:feature New feature or request status:help-wanted Open for contributors

Comments

@ForNeVeR
Copy link
Owner

ForNeVeR commented Nov 23, 2023

In #354, we've introduced FuncPtr interop: C code may call .NET Core and pass function pointers in the positions when FuncPtr<TDelegate> is expected.

Currently, we are limited to 16 parameters for each such function because there are no longer delegate types in .NET runtime.

We should support functions of any length instead, perhaps by inventing a custom calling convention on ValueTuples.

While implementing it, seek for number 493 in the code.

@ForNeVeR ForNeVeR added kind:feature New feature or request status:help-wanted Open for contributors area:cil-interop Related to CIL (.NET) interop labels Nov 23, 2023
@BadRyuner
Copy link
Contributor

Why not use function pointer (delegate* managed <Arg1, Arg2, Arg3, etc, RetType>) instead of System.Delegate?
delegate* <> is a void*.
You can get the pointer via ldftn .
And you can call the pointer via calli . Callsite is a signature like <Arg1, Arg2, etc, RetType> + AdditionalFlags (like cdecl/stdcall or managed callin convention). If non-Managed callconv is selected, dotnet adds anti-exception barriers, but it is slightly slower. You can also call native methods in this way. For callback things and all that.
The maximum number of arguments is many times more than 16.
Since delegate*<> is an intptr, there is no runtime checking of arguments. I.e. you can call Foo(int, int) as Foo(int) or Foo(int,int,int). Hence a funny error. If you call Foo(float) as Foo(int), the latter will not get float because float is passed through Xmm1 registers and int is passed through RCX (on x64, if I remember correctly.

@ForNeVeR
Copy link
Owner Author

ForNeVeR commented Feb 26, 2024

I will split your question into several parts.

  1. Why not use (function) pointers directly? Because they don't have a constant size, and for the Wide architecture, we need a portable pointer of exactly 8 bytes. Feel free to skim over the corresponding documentation.
  2. Why not use a function pointer as an argument for FuncPtr? Because that's impossible. Pointer types can't be used as generic arguments.
  3. Do we have to use all that stuff at all? No, we do not have. If compiling against native architectures1, Cesium doesn't emit CPtr / VoidPtr / FuncPtr interop, and uses the function pointers directly.

Footnotes

  1. Everything except Wide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:cil-interop Related to CIL (.NET) interop kind:feature New feature or request status:help-wanted Open for contributors
Projects
None yet
Development

No branches or pull requests

2 participants