Calling C Libraries with dart:ffi
Bind to native shared libraries and marshal structs and pointers through dart:ffi.
Why dart:ffi?
dart:ffi is Dart's Foreign Function Interface. It lets your Flutter app call functions in native C shared libraries (.so, .dylib, .dll, or the iOS process image) directly, with no platform-channel round-trip.
- Synchronous by default and very low overhead, unlike
MethodChannelwhich serializes messages across an async boundary. - Ideal for CPU-heavy code, existing C/C++/Rust libraries, and OS-level APIs (sqlite, libsodium, image codecs).
- You bind a C signature to a Dart signature, then call it like an ordinary function.
The cost: you manage memory and types yourself. Get a pointer or a struct layout wrong and you crash the whole process.
Opening a DynamicLibrary
Everything starts with a DynamicLibrary. It is the handle to the loaded native code from which you look up symbols.
DynamicLibrary.open(path)loads a shared library by file name. On Android use'libfoo.so'; on iOS/macOS code is usually statically linked, so useDynamicLibrary.process()orDynamicLibrary.executable().- Pick the right name per platform with
Platform.isAndroid/Platform.isIOS.
import 'dart:ffi';
import 'dart:io' show Platform;
DynamicLibrary openNativeLib() {
if (Platform.isAndroid) {
return DynamicLibrary.open('libnative_math.so');
}
if (Platform.isIOS || Platform.isMacOS) {
// Symbols are linked into the app process on iOS.
return DynamicLibrary.process();
}
if (Platform.isWindows) {
return DynamicLibrary.open('native_math.dll');
}
return DynamicLibrary.open('libnative_math.so');
}