Dart mobile, command-line, and server apps running on the Dart Native platform can use the dart:ffi library to call native C APIs. FFI stands for foreign function interface. Other terms for similar functionality include native interface and language bindings.
API documentation is available from the dev channel: dart:ffi API reference.
Examples
The following examples show how to use the dart:ffi library:
Example | Description |
hello_world | How to call a C function with no arguments and no return value. |
primitives | How to call C functions that have arguments and return values that are ints or pointers. Also demonstrates varargs. |
structs | 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 has the minimum necessary code for calling a C library.
Files
The hello_world example has the following files:
Source file | Description |
hello.dart | A Dart file that uses the hello_world() function from a C library. |
pubspec.yaml | The usual Dart pubspec, with a lower bounds on the SDK that’s at least 2.6. |
hello_library/hello.h | Declares the hello_world() function. |
hello_library/hello.c | A C file that imports hello.h and defines the hello_world() function. |
hello_library/CMakeLists.txt | A CMake build file for compiling the C code into a dynamic library. |
Building the C library creates several files,
including a dynamic library file named
libhello.dylib
(macOS), libhello.dll
(Windows), or
libhello.so
(Linux).
Building and running
Here’s an example of building the dynamic library and executing the Dart app:
$ cd hello_library
$ cmake .
...
$ make
...
$ cd ..
$ dart run hello.dart
Hello World
Using dart:ffi
The hello.dart
file
illustrates the steps for using dart:ffi to call a C function:
- Import dart:ffi.
- Create a typedef with the FFI type signature of the C function.
- Create a typedef for the variable that you’ll use when calling the C function.
- Open the dynamic library that contains the C function.
- Get a reference to the C function, and put it into a variable.
- Call the C function.
Here’s the code for each step.
- Import dart:ffi.
import 'dart:ffi' as ffi;
- Create a typedef with the FFI type signature of the C function.
Commonly used types defined by dart:ffi library includeDouble
,Int32
,NativeFunction
,Pointer
,Struct
,Uint8
, andVoid
.typedef hello_world_func = ffi.Void Function();
- Create a typedef for the variable that you’ll use when calling the C function.
typedef HelloWorld = void Function();
- Open the dynamic library that contains the C function.
final dylib = ffi.DynamicLibrary.open('hello_world.dylib');
- 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();
- 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 the following: