sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Implement support for creating isolate independent native functions code in dart:ffi

Open mraleph opened this issue 3 years ago • 12 comments

The idea of isolate independent native code is described in finalization proposal

mraleph avatar Nov 25 '21 15:11 mraleph

Assigning to myself for the initial design.

mraleph avatar Nov 25 '21 15:11 mraleph

Another use case for this is async callbacks: we could potentially compile a function using the Dart API turning a callback into Dart_PostCObject. (Instead of implementing that in the VM or as a way of implementing that in the VM.)

  • https://github.com/dart-lang/sdk/issues/37022

dcharkes avatar Apr 22 '22 15:04 dcharkes

@mraleph is this work complete sufficiently to close out the issue?

itsjustkevin avatar May 05 '22 14:05 itsjustkevin

This is in early design stages.

mraleph avatar May 05 '22 15:05 mraleph

half year passed and only 2 month left to Dart 2.18 release, any update on this?

calvin2021y avatar Jun 12 '22 06:06 calvin2021y

@dcharkes has done some initial prototyping and we have been discussing different approaches.

It currently looks possible that we decide against implementing isolate independent code as a embedded DSL and choose to follow cgo route instead - simplify bundling C/C++ code with the Dart packages as this would address the same problem in a more robust way. But the final decision is not yet made.

mraleph avatar Jun 13 '22 09:06 mraleph

@calvin2021y We have a prototype on https://dart-review.googlesource.com/c/sdk/+/246241/ if you know how to build the Dart SDK and want to try it out.

dcharkes avatar Jun 13 '22 09:06 dcharkes

@dcharkes has done some initial prototyping and we have been discussing different approaches.

It currently looks possible that we decide against implementing isolate independent code as a embedded DSL and choose to follow cgo route instead - simplify bundling C/C++ code with the Dart packages as this would address the same problem in a more robust way. But the final decision is not yet made.

I like this much better, will try the Dart SDK branch.

calvin2021y avatar Jun 15 '22 05:06 calvin2021y

Any update about this @calvin2021y ?

jacobaraujo7 avatar Jul 29 '22 12:07 jacobaraujo7

@dcharkes @mraleph will this be going into 2.19? Asking for documentation update purposes

MaryaBelanger avatar Sep 16 '22 15:09 MaryaBelanger

@dcharkes @mraleph will this be going into 2.19? Asking for documentation update purposes

No. We're exploring bundling C/C++ code with Dart packages instead.

dcharkes avatar Sep 19 '22 06:09 dcharkes

Cleared the milestone to reflect the change in our plans.

mraleph avatar Sep 19 '22 07:09 mraleph

Side note, if you just need a finalizer to reliably free a pointer, this works without any extra C code for a guaranteed freeing of your native resources:

// filename: lib/src/utils/memory.dart

/// A generic [NativeFinalizer] to free any pointer by calling the C function
/// `free`. It's kind of like a workaround to combat the restriction of
/// [NativeFinalizer] (which only accepts a C function, not a Dart
/// function).
final freenalizer = NativeFinalizer(DynamicLibrary.executable().lookup('free'));

Then,

import 'dart:ffi';
import 'package:mypackage/src/utils/memory.dart';

class Foo extends Finalizable {
  Pointer<X> _ptr = calloc();
  Foo() {
    freenalizer.attach(this, _ptr.cast());
  }
}

GZGavinZhao avatar Oct 03 '22 15:10 GZGavinZhao

Side note, if you just need a finalizer to reliably free a pointer, this works without any extra C code for a guaranteed freeing of your native resources:

// filename: lib/src/utils/memory.dart

/// A generic [NativeFinalizer] to free any pointer by calling the C function
/// `free`. It's kind of like a workaround to combat the restriction of
/// [NativeFinalizer] (which only accepts a C function, not a Dart
/// function).
final freenalizer = NativeFinalizer(DynamicLibrary.executable().lookup('free'));

Then,

import 'dart:ffi';
import 'package:mypackage/src/utils/memory.dart';

class Foo extends Finalizable {
  Pointer<X> _ptr = calloc();
  Foo() {
    freenalizer.attach(this, _ptr.cast());
  }
}

That is not entirely true. On Windows WinCoTaskMemFree needs to be used when using calloc from package:ffi. See https://github.com/dart-lang/native/issues/910 for making an abstraction for this.

dcharkes avatar Oct 03 '22 16:10 dcharkes

How would you embed C++ code when compiling Dart as an AOT executable and when running in JIT mode?

Keithcat1 avatar Oct 08 '22 20:10 Keithcat1

How would you embed C++ code when compiling Dart as an AOT executable and when running in JIT mode?

Currently, you bundle dynamic libraries.

  • In Flutter use the FFI plugin template.
  • In Dart standalone, use a bin/setup.dart script that downloads or builds your dynamic libraries. (Note your downstream users need to all run dart run yourpackage:setup before stuff works.

This is not ideal.

Future:

  • You add your C++ code to the pub package and create a bin/native.dart CLI that can be invoked by the dart run and dart compile commands to build the native assets (static or dynamic library). Then use FfiNative for a more declarative binding. This is WIP. Some related issues:
    • https://github.com/dart-lang/sdk/issues/49803 (design is out of date)
    • https://github.com/dart-lang/sdk/issues/50097
  • JIT will only support dynamic libraries. But in AOT we should be able to link in static libraries and let the native linker get rid of code that is not referenced (https://github.com/dart-lang/sdk/issues/49418). I built a prototype of this in https://dart-review.googlesource.com/c/sdk/+/251263. This is also very much WIP.

dcharkes avatar Oct 10 '22 10:10 dcharkes