-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Design and implement Dart VM FFI #34452
Comments
A general FFI could also be useful for interaction with JavaScript, so we should consider whether it's possible to make something general wihout compromising on the usability on each platform. The current JS-interop functionality is not a clean design, it should be possible to improve it. |
I would not assume that without talking to @vsmenon. The syntax might leave a little to be desired, but I have no desire to make a breaking change to the syntax unless it vastly improves end users, not just the fact it isn't a "clean design". |
Providing a new syntax / library doesn't necessarily imply removing the existing support. With that in mind, I think @lrhn 's suggestion is good. |
Is this referring to Dart calling C/C++ interfaces or vice versa? |
@krisgiesing Initially it will be Dart calling C, later we would like to extend this to C calling Dart. Though it is very hard to draw a line because we plan to support callbacks as part of the initial offering - so C would be able to call back into Dart. Here is the markdown version of the vision doc (implementation is currently being prototyped). Let me know if you have any comments on that one. |
Conditional compilation is a pain for IDEs. It's worth looking into how Kotlin handles a similar problem with expect/actual declarations on a language level. In a nutshell, |
@matklad the expect/actual stuff is pretty close to interface libraries that were discussed in context of the conditional imports long time ago - exactly to solve IDE problem. However I don't think this went anywhere - and I think conditional imports are pretty much dead. I think in the context of FFI we will be implementing what Structure Layouts and Portability describes. I will amend the section that still talks about conditional imports. |
Any updates for dart lang FFi ? very happy if there have usable FFI . |
@netroby I'm working on it. We plan to add an initial version during Q1. So far the prototype closely follows the vision doc. Let me know whether that covers your use case. |
Seems great, calling C is a must have. Is there a way to get access to the proto? Thanks. |
@fimbault we plan to release prototype for public consumption later this quarter in few stages: first we will land support for FFI in JIT mode on X64 only, then it will be expanded to cover X64, ARM, ARM64 in JIT and AOT. |
are you talking about this: #24581 ? I use it and it is great. |
Are there plans to support calling into shared libraries similar to python's ctypes? |
@robertmuth yes, please see the doc referenced from #34452 (comment) for more details. |
It will be great to have FFI in Dart.
There is proposal for all of them here. For 1. final lib = DynamicLibrary.open('libfoo.so'); It is good approach. However there are some alternative ways: a. Load library manually but return class were all native (or abstract) functions resolved to dynamic library functions: class Foo extends DynamicLibrary {
int add(int a, int b) native;
}
final Foo lib = DynamicLibrary.open<Foo>(Platform.isLinux ? 'libfoo.so' : 'foo.dll');
lib.add(1,2); //3 Dart VM lookup all native function in class automatically. b. The same as a. but use class name as dynamic library name: //mapped to libfoo.so on Linux, to libfoo.dylib on macOS and foo.dll on Windows
class Foo extends DynamicLibrary {
int add(int a, int b) native;
}
final Foo lib = new Foo(); This automatic mapping is implemented in native extensions: Dart's library name mapped to dynamic library name. Nothing new. c. The same as a. but use annotation on class: @ffi.Library('foo')
class MyFoo {
int add(int a, int b) native;
}
final Foo lib = new Foo(); If library has different names (for instance OpenGL) than annotation can accept list of names. @ffi.Library('Opengl32.dll', 'libGL.so.1')
class OpenGL {
} d. Don't use class and define library name for each function: @ffi.Library('foo')
int add(int a, int b) native; C# DllImport. e. Use Dart library name as in native extensions For 2. final add = lib.lookupFunction<ffi.Int32 Function(ffi.Int32, ffi.Int32), int Function(int, int)>('add'); isn't great. There are some other options to lookup function automatically: a. Lookup by function name: int add(int a, int b) native; //lookup 'add' function in dynamic library b. Define name after native keyword as in native extensions: int myadd(int a, int b) native 'add'; //lookup 'add' function in dynamic library c. Lookup by name in annotation: @ffi.Function('add')
int myadd(int a, int b) native; // lookup 'add' function in dynamic library It works in for cases 1.a-1.c and for 1.d. For 3. and 4. int add(@ffi.Type('Int') int a, @ffi.Type('Int') int b) where annotation @ffi.Type define C type of parameter. Top C data types should be supported: integer types (char, short, int, long, long long including unsigned), float types, pointers etc. Some real world examples: void srand(@ffi.Type('Uint') int seed); //libc on Linux
@ffi.Type('Ulong') int GetLastError(); //kernel32 on Windows
int SDL_Init(@ffi.Type('Int32') int flags); //SDL cross-platform
void SDL_ShowWindow(@ffi.Type('IntPtr') int window); //SDL cross-platform For instance, SDL uses both platform-independent (int32_t) and platform-dependent (int, int *) types in API. For structs it would be great to have automatic struct packing based on field order, its C type and run-time platform. @ffi.struct({
'x64 && linux': { // Layout on 64-bit Linux
'x': ffi.Field(ffi.Double, 0),
'y': ffi.Field(ffi.Double, 8),
'next': ffi.Field(ffi.Double, 16)
},
'arm && ios': { // Layout on 32-bit iOS
'x': ffi.Field(ffi.Float, 4),
'y': ffi.Field(ffi.Float, 8),
'next': ffi.Field(ffi.Pointer, 0)
},
})
class Point extends ffi.Pointer<Point> {
double x;
double y;
Point next;
} it would be great to write something like: class Point {
@ffi.Type('Double')
double x;
@ffi.Type('Double')
double y;
@ffi.Type('Pointer')
Point next;
} It is enough information for Dart VM to pack structure on each supported platform. @ffi.StructSize(24)
class Point {
@ffi.Offset(0)
@ffi.Type('Double')
double x;
@ffi.Offset(8)
@ffi.Type('Double')
double y;
@ffi.Offset(16)
@ffi.Type('Pointer')
Point next;
} |
Thanks Daco for the prompt reply! So I assume that I must split my single native library into 2 ones. |
@WoodyGuo It looks like you can make calls to the same instance of the same native library from both Java and Dart. This cpp file worked for me (after calling the first function from Java, calling the second one returns 123 to Dart):
The cpp file is linked as a shared library. I have a Java class with |
@mikeperri cool, thanks for the sharing. |
Is C calling Dart supported now? |
Yes, it's supported, but still not entirely complete. See https://dart.dev/guides/libraries/c-interop |
@scriptsman callbacks are supported as well: |
@dcharkes Looking forward to supporting instance(not class) method. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Prototype for `dart:ffi` on Linux/MacOS x64 in JIT mode. `dart:ffi` is experimental and its API is likely to change in the future. Progress and design decisions are tracked in https://github.com/dart-lang/sdk/projects/13 issue: dart-lang#34452 Change-Id: Ifa4566388e42c8757f154741d11e303465ef305d Cq-Include-Trybots: luci.dart.try:vm-kernel-optcounter-threshold-linux-release-x64-try, vm-kernel-precomp-linux-debug-x64-try, vm-kernel-precomp-linux-release-simarm-try, vm-kernel-precomp-linux-release-simarm64-try, vm-kernel-precomp-linux-release-x64-try, vm-kernel-precomp-mac-release-simarm64-try, vm-kernel-precomp-win-release-x64-try, vm-kernel-mac-debug-x64-try, vm-kernel-asan-linux-release-x64 Reviewed-on: https://dart-review.googlesource.com/c/80124 Reviewed-by: Samir Jindel <sjindel@google.com> Auto-Submit: Daco Harkes <dacoharkes@google.com>
Closing as We will still actively adding new features to |
does this work w/ emscripten on the wasm side? |
No, not yet. This is tracked in: |
The present feature tracks the implementation of Dart FFI support enabling interop with C & C++ code from Dart.
Status
The feature will be in stable as of Dart 2.12. More details here:
https://dart.dev/guides/libraries/c-interop
For any discussion of this feature, or feedback or questions regarding the feature, kindly join and post the dart-ffi group: https://groups.google.com/forum/#!forum/dart-ffi
We will still actively adding new features to
dart:ffi
. Please refer to library-ffi for open issues and feature requests.Background
Some inspirational references:
The text was updated successfully, but these errors were encountered: