Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
153 lines (116 sloc) 5.5 KB
title description hw samples sqllite
C interop using dart:ffi
To use C code in your Dart program, use the dart:ffi library (currently in preview).

Dart mobile, command-line, and server apps running on the Dart Native platform can use the dart:ffi library to call native C APIs. The ffi name stands for foreign function interface. Other terms for similar functionality include native interface and language bindings.

{{ site.alert.note }} The dart:ffi library is in active development and isn't complete yet. Note that the API is likely to have breaking changes between now and its completion, as we add polish and broaden support for common patterns.

Usage of the feature requires a Dart 2.6.x dev channel build. {{ site.alert.end }}

API documentation is available from the dev channel: API reference documentation.

Examples

The following examples show how to use the dart:ffi library:

| Example | Description | | [hello_world][] | Shows how to call a C function with no arguments and no return value. | | [primitives][] | Shows how to call C functions that have arguments and return values that are ints or pointers. Also demonstrates using varargs. | [structs][] | Shows how to use structs to pass strings to and from C and to handle simple and complex C structures. | | [sqllite][] | An example in the Dart SDK repo that comes with a [mini tutorial.][] |

Walkthrough of hello_world

The [hello_world example][hello_world] has the minimum necessary code for calling a C library.

Files

The hello_world example has the following files:

| Source file | Description | | [hello.dart]({{ page.hw}}/hello.dart) | A Dart file that uses the hello_world() function from a C library. | | [pubspec.yaml]({{ page.hw}}/pubspec.yaml) | The usual Dart pubspec, with a lower bounds on the SDK that's at least 2.5. | | [c/hello.h]({{ page.hw}}/c/hello.h) | Declares the hello_world() function. | | [c/hello.c]({{ page.hw}}/c/hello.c) | A C file that imports hello.h and defines the hello_world() function. | | [c/Makefile]({{ page.hw}}/c/Makefile) | A macOS-specific build file that compiles the C code into a dynamic library. | {:.table .table-striped }

{% comment %} [PENDING: say something about setup.sh? It doesn't seem necessary for this example, but maybe it's needed by other examples?]

{% endcomment %}

Building the C library creates two additional files:

| Generated file | Description | | hello_world.dylib | The dynamic library loaded by the Dart app. | | c/hello.o | An intermediate object file. | {:.table .table-striped }

Building and running

Here's an example of building the dynamic library and executing the Dart app:

$ cd c
$ make dylib
gcc -dynamiclib -undefined suppress -flat_namespace hello.o -o ../hello_world.dylib
$ cd ..
$ dart hello.dart
Hello World
$ 

Using dart:ffi

The [hello.dart file]({{ page.hw}}/hello.dart) illustrates the steps for using dart:ffi to call a C function:

  1. Import dart:ffi.
  2. Create a typedef with the FFI type signature of the C function.
  3. Create a typedef for the variable that you'll use when calling the C function.
  4. Open the dynamic library that contains the C function.
  5. Get a reference to the C function, and put it into a variable.
  6. Call the C function.

Here's the code for each step.

  1. Import dart:ffi.
import 'dart:ffi' as ffi;
  1. Create a typedef with the FFI type signature of the C function.
    Commonly used types defined by dart:ffi library include Double, Int32, NativeFunction, Pointer, Struct, Uint8, and Void.
typedef hello_world_func = ffi.Void Function();
  1. Create a typedef for the variable that you'll use when calling the C function.
typedef HelloWorld = void Function();
  1. Open the dynamic library that contains the C function.
  final dylib = ffi.DynamicLibrary.open('hello_world.dylib');
  1. Get a reference to the C function, and put it into a variable. This code uses the typedefs defined in steps 2 and 3, along with the dynamic library variable from step 4.
  final HelloWorld hello = dylib
      .lookup<ffi.NativeFunction<hello_world_func>>('hello_world')
      .asFunction();
  1. Call the C function.
  hello();

Once you understand the hello_world example, you should be ready to look at the other dart:ffi examples.

Bundling and loading C libraries

How you bundle (or package or distribute) a C library with your package or app and then load that library depends on your platform and the type of library. For details, see Binding to native code via FFI.

[hello_world]: {{ page.hw }} [primitives]: {{ page.samples }}/primitives [structs]: {{ page.samples }}/structs [sqllite]: {{ page.sqllite }} [mini tutorial.]: {{ page.sqllite }}/docs/sqlite-tutorial.md

You can’t perform that action at this time.