dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.08k stars 1.56k forks source link

Design and implement Dart VM FFI #34452

Closed mraleph closed 3 years ago

mraleph commented 6 years ago

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 https://github.com/dart-lang/sdk/labels/library-ffi for open issues and feature requests.

Background

Some inspirational references:

truongsinh commented 5 years ago

What's the plan in releasing ffi on flutter? Should I stick to platform channel or should I investigate in exporting native extension myself or just wait for ffi. DESPERATE for calling cpp from dart, these is too much existing code in cpp to rewrite.

From what I understand, we can already use FFI on Android, both debug and release, but the functionality is limited, and API subject to change. I have not found any example on iOS, nor the status of iOS in general.

Ref https://github.com/dart-lang/sdk/issues/37224#issuecomment-517663205

sjindel-google commented 5 years ago

@truongsinh is correct, although iOS is supported equally well as Android. See https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFI for details on iOS.

truongsinh commented 5 years ago

@truongsinh is correct, although iOS is supported equally well as Android. See https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFIl for details on iOS.

A small typo in your link, 1 I too much at the and of the link (FFI vs FFII)

sjindel-google commented 5 years ago

Thanks, corrected.

truongsinh commented 5 years ago

@sjindel-google I was able to create an extremely simple example on iOS

You can see in Swift code I use @_cdecl to declare C interface. Should this be mentioned in the wiki page?

sjindel-google commented 5 years ago

Sure, feel free to edit the Wiki page!

truongsinh commented 4 years ago

Should https://github.com/dart-lang/sdk/issues/3691 be re-considered in the interest of FFI?

dcharkes commented 4 years ago

See https://github.com/dart-lang/sdk/issues/35770.

WoodyGuo commented 4 years ago

Just went through a simple ffi demo and it worked well.

I have a question though, can i call Java methods from c code which is loaded via ffi on an Android device?

dcharkes commented 4 years ago

@WoodyGuo You would have to use JNI for that.

WoodyGuo commented 4 years ago

@WoodyGuo You would have to use JNI for that.

Thanks Daco for the prompt reply!

So I assume that I must split my single native library into 2 ones. One is to be loaded from Java via System.loadLibrary, and the other is to be loaded from Dart via FFI. So what would you suggest to use to call code in one library from the other one?

dart_ffi
mikeperri commented 4 years ago

@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):

extern "C" {
    int32_t setByJava = 0;

    JNIEXPORT void JNICALL
    Java_com_michaeljperri_flutter_1plugin_FlutterPlugin_native_1setValue(JNIEnv *env, jobject instance) {
        setByJava = 123;
    }

    __attribute__((visibility("default"))) __attribute__((used))
    int32_t get_val_from_java(const char* filename) {
        return setByJava;
    }
}

The cpp file is linked as a shared library. I have a Java class with System.loadLibrary("my_plugin") and a Dart file with DynamicLibrary.open("libmy_plugin.so").

WoodyGuo commented 4 years ago

@mikeperri cool, thanks for the sharing.

scriptsman commented 4 years ago

Is C calling Dart supported now?

mit-mit commented 4 years ago

Yes, it's supported, but still not entirely complete. See https://dart.dev/guides/libraries/c-interop

scriptsman commented 4 years ago

@mit-mit Thank you.But it seems that the examples only show how to call C functions in dart.And I want to know if invoking a dart method from the C/C++ code is supported now , just like the end of this page?

dcharkes commented 4 years ago

@scriptsman callbacks are supported as well:

And here and here is the native code for both samples.

xuchaoqian commented 4 years ago

@dcharkes Looking forward to supporting instance(not class) method.

listepo commented 3 years ago

Is it possible to add debugging for ide?

art(11490,0x7000070ec000) malloc: *** error for object 0x10fcb0efc: pointer being freed was not allocated
dart(11490,0x7000070ec000) malloc: *** set a breakpoint in malloc_error_break to debug
dcharkes commented 3 years ago

@listepo In order to get C/C++ debugging, you need to run the C/C++ debugger on the Dart executable. For more details refer to https://github.com/dart-lang/ffi/issues/47.

listepo commented 3 years ago

@dcharkes thank you so much

listepo commented 3 years ago

I am facing a problem when working with strings. For example: https://github.com/postgres/postgres/blob/8a15e735be00f156a7227741c0ce88702e6de099/src/interfaces/libpq/fe-connect.c#L6535

char *
PQpass(const PGconn *conn)
{
    char       *password = NULL;

    if (!conn)
        return NULL;
    if (conn->connhost != NULL)
        password = conn->connhost[conn->whichhost].password;
    if (password == NULL)
        password = conn->pgpass;
    /* Historically we've returned "" not NULL for no password specified */
    if (password == NULL)
        password = "";
    return password;
}

when I use https://github.com/dart-lang/native/issues/508 I get an error

art(11490,0x7000070ec000) malloc: *** error for object 0x10fcb0efc: pointer being freed was not allocated
dart(11490,0x7000070ec000) malloc: *** set a breakpoint in malloc_error_break to debug

I guess the error occurs when the function returns an empty string(password = "";) and I try to free memory.(for strings without malloc) How can I understand when I need to free up memory, and when not?(password = conn->pgpass; with malloc)

dcharkes commented 3 years ago

Please open a new issue instead of slow-chatting on this one. Feel free to tag me.

mraleph commented 3 years ago

Please open a new issue instead of slow-chatting on this one. Feel free to tag me.

@listepo or even better use mailing list to ask questions. Issue tracker exists primarily for bug reports and feature requests, not questions.

xuchaoqian commented 3 years ago

@listepo two ways: 1) return NULL instead of ""; 2) check the length of password; if the length is = 0, just ignore it.

listepo commented 3 years ago

@dcharkes @mraleph sorry for the spam. I think the new issue is better, the answer can help not only me

dcharkes commented 3 years ago

Closing as dart:ffi has now been marked stable.

We will still actively adding new features to dart:ffi. Please refer to https://github.com/dart-lang/sdk/labels/library-ffi for open issues and feature requests.

unicomp21 commented 9 months ago

does this work w/ emscripten on the wasm side?

dcharkes commented 9 months ago

does this work w/ emscripten on the wasm side?

No, not yet. This is tracked in: