Description
Context: https://github.com/dotnet/csharplang/blob/master/proposals/function-pointers.md
Context: dotnet/runtime#32963
There is a proposal to add function pointers to the C# language. This would allow obtaining a pointer to a C# static
method and hand it to native code without going through Delegates, and would be more efficient.
By @jonpryor's reading of the spec, In order to create a function pointer which can be handed off to native code, the method needs to have a [NativeCallableAttribute]
declaration, but:
Methods marked by [
[NativeCallable]
] attribute are only callable from native code, not managed (can’t call methods, create a delegate, etc …).
This restriction means that we can't use the existing JNINativeWrapper.CreateDelegate()
approach, which is used as part of exception marshaling, e.g.
The "easiest" way to support C# function pointers, if/when they ever exist, will be to integrate support into jnimarshalmethod-gen
, such that instead of emitting
partial class __<$>_jni_marshal_methods {
public static IntPtr FuncIJavaObject (IntPtr __jnienv, IntPtr __this) {…}
public static void __RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
{
args.AddRegistrations (new JniNativeMethodRegistration[]{
new JniNativeMethodRegistration ("funcIJavaObject",
"()Ljava/lang/Object;",
new Func<IntPtr, IntPtr, IntPtr> (FuncIJavaObject)),
…
});
}
}
We would emit "equivalent" code which uses [NativeCallable]
and function pointers:
partial class __<$>_jni_marshal_methods {
[NativeCallable]
public static IntPtr FuncIJavaObject (IntPtr __jnienv, IntPtr __this) {…}
public static void __RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
{
delegate*<IntPtr, IntPtr> fp = &FuncIJavaObject;
args.AddRegistrations (new JniNativeMethodRegistration[]{
new JniNativeMethodRegistration ("funcIJavaObject",
"()Ljava/lang/Object;",
(IntPtr) fp),
…
});
}
}
Note that for the above to work, we'd need to add a JniNativeMethodRegistration(string, string, IntPtr)
constructor, which may be difficult to do without an ABI break, as that type only exposes fields, not properties, and we can't change the size of that struct:
I doubt anybody is currently using this struct, so it might not be a problem to break ABI, but if it is, we'll need to think of a workaround.