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

[vm/ffi] Static @NativeCallbacks API #51383

Open
dcharkes opened this issue Feb 13, 2023 · 1 comment
Open

[vm/ffi] Static @NativeCallbacks API #51383

dcharkes opened this issue Feb 13, 2023 · 1 comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi

Comments

@dcharkes
Copy link
Contributor

dcharkes commented Feb 13, 2023

@mkustermann suggested we should have static binding for native callbacks as well, as the dual for the @Native external functions.

We would move the information from Pointer.fromFunction to the declaration site (static functions):

@NativeCallback<void Function()>(
  exportAs: 'setupPrint',
  exceptionalReturn: <...>,
  callbackSemantics: <...>,
)
void setupPrint() {}

void main(){
  final callbackPointer = Pointer.addressOf<void Function()>(setupPrint);
}

Having this more static information would make it in the future possible to compile a Dart aot snapshot in such a way to statically link unresolved symbols from C static libraries to the Dart functions (or rather the FFI callback trampolines for these). The dual to:

The NativeCallback definition would look something like:

/// Annotation specifying how to bind a Dart function to native code.
///
/// The annotation applies only to static function declarations.
///
/// Example:
///
/// [...]
///
/// NOTE: This is an experimental feature and may change in the future.
@Since('3.1')
class NativeCallback<T> {
  /// If an exception is thrown while calling the function this annotation is on,
  /// the native function will return [exceptionalReturn],
  /// which must be assignable to return type of [T].
  final Object? exceptionalReturn;

  /// The threading semantics when this function is called from native.
  ///
  /// See the documentation on [CallbackSemantics].
  final CallbackSemantics semantics;

  /// The name to be made available to the native linker.
  ///
  /// Defaults to the function name when omitted.
  ///
  /// Example:
  ///
  /// [...]
  ///
  /// Prefer omitting the [symbol] when possible.
  final String? exportAs;

  const Native({
    this.exceptionalReturn,
    this.semantics = CallbackSemantics.alreadyEnteredCorrectIsolate,
    this.exportAs,
  });
}

@Since('3.1')
class CallbackSemantics {
  CallbackSemantics._();

  /// [...]
  static const CallbackSemantics alreadyEnteredCorrectIsolate = ...;

  /// [...]
  static const CallbackSemantics asyncVoid = ...;
}

The exportAs could also be used to generate a C API as proposed earlier by @vegorov in internal doc. This could then be used by our embedders instead of the reflective API currently in use.

This would prevent using the same Dart function as callback with two different settings, but that could be worked around by creating two top level functions with differing @NativeCallback annotations.

The new API would not support closures (which is also prohibited in the current API). But, for closures we likely need some API that would enable us to weakly hold on to an isolate and tell an isolate that a closure can be released.

Related issues:

cc @liamappelbe, @mkustermann, @mraleph

@dcharkes
Copy link
Contributor Author

dcharkes commented Jan 26, 2024

Syntax suggested in dart-lang/language#3531

// Callback semantics should always be NativeCallable.shared
@Export<void Function()>(
  exportAs: 'setupPrint', // optional
  exceptionalReturn: <...>, // only required for types it's currently required for `NativeCallable`s
)
void setupPrint() {}

I like using "export".

We could also consider "extern" which is used in C++ and Rust.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi
Projects
None yet
Development

No branches or pull requests

1 participant