Skip to content

Instantly share code, notes, and snippets.

@loic-sharma
Last active April 2, 2025 00:13
Show Gist options
  • Save loic-sharma/e4b66efd5b6bac3521218872073ab387 to your computer and use it in GitHub Desktop.
Save loic-sharma/e4b66efd5b6bac3521218872073ab387 to your computer and use it in GitHub Desktop.
FFI to embedders design

Practical example

Framework

Let's say I have this high-level API in the framework:

abstract class Greeter {
  void greet(String name);
}

This needs to use platform-specific APIs. Here's what the Windows implementation might look like:

// This type exists in the framework and uses FFI to the Windows embedder.
class WindowsGreeter implements Greeter {
  @override
  void greet(String name) {
   final int engineId = PlatformDispatcher.instance.engineId!;
   final Pointer<ffi.Utf8> namePtr = name.toNativeUtf8();
   _greet(engineId, namePtr);
   ffi.malloc.free(namePtr);
  }
  
  @Native<Void Function(Int64, Pointer<ffi.Utf8>)>(symbol: 'FlutterPrivateGreet')
  external static void _greet(int engineId, Pointer<ffi.Utf8> name);
}

Embedder

The embedder provides a C API for the framework's FFI.

For example, here's what that would look like in the Windows embedder:

extern "C" {

FLUTTER_EXPORT
void FlutterPrivateGreet(int64_t engine_id, const char* name);

} // extern "C"

Out-of-tree embedders

This pattern supports out-of-tree embedders.

Let's say the Greeter powers a widgets-layer feature. The WidgetsBinding can expose a field for the Greeter implementation:

mixin WidgetsBinding ... {

  @override
  void initInstances() {
    if (Platform.isWindows) {
      greeter = WindowsGreeter();
    }
  }

  late Greeter greeter;
}

At startup, the out-of-tree embedder registers its custom Greeter implementation with the framework:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  if (isOutOfTreeEmbedder) {
    WidgetsBinding.instance.greeter = OutOfTreeGreeter();
  }

  runApp(...);
}

This is the same pattern that the framework uses for the PlatformMenuDelegate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment