Introduction
This content is for v1. Switch to the latest version for up-to-date documentation.
dart_cpp_bridge is a Dart ↔ C++20 interoperability bridge library, inspired by Flutter Rust Bridge. It lets existing C/C++ code expose APIs to Dart/Flutter with an experience close to Dart async / await / Stream, while business C++ code only needs to be written as ordinary functions or async_simple::coro::Lazy<T> coroutines.
What it can do
Section titled “What it can do”- Synchronous calls:
BRIDGE_SYNCfunctions return directly; Dart-side calls are synchronous - Asynchronous coroutines:
BRIDGE_ASYNCfunctions returnLazy<T>, which canco_awaitsuspend on the bridge io thread without blocking the thread - Stream flows: C++ continuously pushes data to Dart via
StreamSink - DartFn reverse calls: C++ calls Dart closures (
Future-style), supporting argument-based and persistent callbacks - C++ exception propagation: C++ exceptions are caught at the wire boundary and encoded as Dart exceptions, without crashing the process
- Code generation: Parses
BRIDGE_*markers in C++ headers and auto-generates Dart FFI bindings, wire dispatch, and serialization code - Cross-platform: Supports Windows, Linux, macOS, iOS, and Android
- Pure C API:
cbridge.h+dcb_codec.hprovide C99-compatible callback-style entry points for pure C projects or other language runtimes - External runtime integration: libuv, glib, and custom event loops can plug into the bridge coroutine system via
ForeignExecutor - Coroutine channels:
co::oneshot/co::mpscbuild non-blocking pipelines across threads / runtimes
Design philosophy
Section titled “Design philosophy”Core principle:
Business C++ code is written as ordinary functions or
async_simple::coro::Lazy<T>; the bridge layer handles encoding/decoding, scheduling, and Dart API generation.
Architecture overview
Section titled “Architecture overview”Dart Isolate(s) Session per Isolate (one long-lived reply port) Future / Stream / DartFn callbacks ⇅ FFI binary framesRuntime (process-wide) asio::io_context (single-threaded) + AsioExecutor asio::thread_pool (blocking / normal work) wire: sync / async Lazy / stream / DartFn- Runtime: Process-wide singleton containing the
asio::io_contextevent loop,AsioExecutor, and blocking thread pool - Session: One Session per Isolate that calls
DartCppBridge.init(), managing the reply port and DartFn closure registry - Wire: Little-endian binary frames; C++ exceptions are caught at the wire boundary and encoded as error frames, never crossing FFI
Built-in basic runtime
Section titled “Built-in basic runtime”The bridge includes a built-in runtime based on asio + async-simple. Business code usually does not need to create its own event loop or executor. You can use it directly:
dcb::spawn/spawn_detached/spawn_blocking— start coroutines and offload blocking tasksco::oneshot/co::mpsc— coroutine channelsasync_simple::coro::sleep— non-blocking timers (backed byasio::steady_timer)
See Basic Runtime and async-simple Coroutines Primer for details.
Technology stack
Section titled “Technology stack”| Layer | Technology | Notes |
|---|---|---|
| C++ standard | C++20 | Coroutines, concepts; requires a recent MSVC / GCC / Clang |
| Event loop | Asio standalone | Single-threaded io_context |
| Coroutines and channels | async-simple | Lazy, Executor; bridge provides co::oneshot / co::mpsc on top |
| Queue | moodycamel::ConcurrentQueue | Lock-free queue underlying co::mpsc |
| Dart side | Dart 3 + package:ffi |
Isolates, ReceivePort, Completer / Stream |
| Code generation | Python 3.13 + libclang-ng | Parses C++ headers to generate bindings; toolchain version is locked |
| Build | CMake 3.24+ | FetchContent pulls Asio / async-simple / ConcurrentQueue |
Next steps
Section titled “Next steps”- Quick Start — create a project, install tools, generate your first bindings
- Architecture Design — core components and call flow
- Marker Selection Guide — choose
BRIDGE_SYNC/ASYNC/NORMAL/Stream/DartFn - Streams — required and optional streams with
StreamSink - Lifecycle Management — Runtime, Session, Opaque objects, NativeFinalizer
- Exceptions and Error Handling — C++ ↔ Dart exception propagation rules
- Project Directory Structure — hand-written files and generated artifacts
- Native Assets Build Hooks — how
hook/build.dartcompiles and bundles the C++ library - C++ ↔ Dart Type Encoding — how C++ types map to Dart types
- Basic Runtime — Runtime, spawn, channel, sleep
- async-simple Coroutines Primer —
Lazy,Executor,co_awaitbehavior - Type Mapping — C++ ↔ Dart types and constraints