Skip to content

Add Native interop documentation section (Pigeon, FFIgen, JNIgen, dart:ffi) - #13995

Open
lamek wants to merge 15 commits into
flutter:mainfrom
lamek:native-interop-eap
Open

lamek wants to merge 15 commits into
flutter:mainfrom
lamek:native-interop-eap

Conversation

@lamek

@lamek lamek commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Description of what this PR is changing or adding, and why:

Adds the new top-level Native interop documentation section (/interop) for the upcoming Flutter 3.50 / Native Interop GA release:

  • Overview (/interop): Decision tree (Mermaid flowchart and step-by-step walkthrough), packaging options, tool comparison matrix, and 3-layer interop architecture.
  • Pigeon (/interop/pigeon): Covers Pigeon with native interop (direct FFI on iOS/macOS and JNI on Android) and Pigeon with platform channels, developer workflow, examples, and constraints.
  • FFIgen (/interop/ffigen): Covers generating C, Objective-C, and Swift bindings with tool/ffigen.dart, developer workflow, examples, and platform/runtime considerations.
  • JNIgen (/interop/jnigen): Covers generating Java and Kotlin bindings on Android with tool/jnigen.dart, developer workflow, examples, and threading/reference lifecycle considerations.
  • dart:ffi (/interop/dart-ffi): Covers native memory allocation, data conversion (package:ffi), and isolate concurrency (Isolate.run).
  • Bind to native code (/interop/bind-native-code): Moved from /platform-integration/bind-native-code with a 301 redirect in firebase.json.
  • Platform channels (/platform-integration/platform-channels): Updated to link to the new Native interop overview and dedicated Pigeon guide.
  • Sidenav (sites/docs/src/data/sidenav/default.yml): Adds the top-level Native interop section above Platform integration.

Issues fixed by this PR (if any):

PRs or commits this PR depends on (if any):

N/A (Draft for early review and staging preview before Flutter 3.50 release)

Presubmit checklist

  • If you are unwilling, or unable, to sign the CLA, even for a tiny, one-word PR, please file an issue instead of a PR.
  • If this PR is not meant to land until a future stable release, mark it as draft with an explanation.
  • This PR follows the Google Developer Documentation Style Guidelines—for example, it doesn't use i.e. or e.g., and it avoids I and we (first-person pronouns).
  • This PR uses semantic line breaks
    of 80 characters or fewer.

- Add Native interop landing page with decision tree and layers guide
- Add Pigeon guide covering platform channels and native bindings modes
- Add FFIgen guide covering Apple frameworks, C-ABI, and developer flow
- Add dart:ffi guide for native memory allocation and concurrency
- Move bind-native-code into platform-integration/interop/
- Add JNIgen guide for Java/Kotlin and Android bindings
- Update platform-channels to focus on manual message passing
- Update sidenav default.yml with new Native interop section
- Update firebase.json with 301 redirect for bind-native-code

TAG=agy
CONV=a76ca369-bcbf-4f8a-822b-b2d6bdd86f54
- Restore exact text, structure, and headings from the Google Doc
- Remove extraneous code examples from developer flow sections

TAG=agy
CONV=a76ca369-bcbf-4f8a-822b-b2d6bdd86f54
@flutter-website-bot

flutter-website-bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Staged preview of the updated docs.flutter.dev site (updated for commit 650cbb7):

https://flutter-docs-prod--docs-pr13995-native-interop-eap-n5ovjnbf.web.app

@parlough

Copy link
Copy Markdown
Member

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive "Native interop" documentation section, adding new guides for dart:ffi, FFIgen, JNIgen, and Pigeon, along with an overview page to help developers choose the right interop solution. It also updates existing platform integration docs, sidebar navigation, and redirects to point to these new pages. A review comment points out an incorrect API reference in the JNIgen guide, suggesting the use of PlatformDispatcher.instance.scheduleOnPlatformThread instead of runOnPlatformThread.

Comment thread sites/docs/src/content/interop/jnigen.md Outdated

@sfshaza2 sfshaza2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some quibbles but, overall, a great addition to the site! I like the decision graph and would be hesitant to clobber it. I also like the table comparing the approaches.

Comment thread sites/docs/src/content/interop/bind-native-code.md Outdated
Comment thread sites/docs/src/content/interop/dart-ffi.md Outdated
Comment thread sites/docs/src/content/interop/dart-ffi.md Outdated
Comment thread sites/docs/src/content/interop/dart-ffi.md Outdated
Comment thread sites/docs/src/content/interop/ffigen.md
Comment thread sites/docs/src/content/interop/pigeon.md Outdated
Comment thread sites/docs/src/content/interop/pigeon.md Outdated
Comment thread sites/docs/src/content/interop/pigeon.md Outdated
Comment thread sites/docs/src/content/interop/pigeon.md Outdated
Comment thread sites/docs/src/content/interop/pigeon.md Outdated

@sfshaza2 sfshaza2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, once my feedback is incorporated. I'll go ahead and approve, but I'd like approval from a SME. thx! Overall, this looks great!

@tarrinneal tarrinneal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple little clarifications

Comment thread sites/docs/src/content/interop/pigeon.md Outdated
Comment thread sites/docs/src/content/interop/index.md
Comment thread sites/docs/src/content/interop/pigeon.md
Comment thread sites/docs/src/content/platform-integration/platform-channels.md
@lamek
lamek marked this pull request as ready for review October 29, 2026 01:38
@lamek
lamek requested a review from a team as a code owner October 29, 2026 01:38

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request restructures the documentation by introducing a new 'Native interop' section, adding dedicated guides for dart:ffi, FFIgen, JNIgen, and Pigeon, and updating existing files to link to these new paths. Feedback on these changes includes a suggestion to flatten the sidebar navigation under 'Native interop' to make dart:ffi and 'Bind to native code' more discoverable, as well as a correction in the FFIgen guide to use .cast<T>() instead of .as() for casting Objective-C objects to avoid compilation errors.

Comment thread sites/docs/src/data/sidenav/default.yml
Comment thread sites/docs/src/content/interop/ffigen.md

@mariamhas mariamhas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments that need to be addressed before this is published

Comment thread sites/docs/src/content/interop/index.md Outdated
regenerate the bindings.
:::

## Examples

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should confirm with @liamappelbe if there is a published package on pub.dev that use jnigen that would be a good example to add here

Comment thread sites/docs/src/content/interop/ffigen.md Outdated
and regenerate the bindings.
:::

## Example

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar comment to jnigen doc, we definitely have packages on pub.dev that use ffigen in production. @liamappelbe or @jwill should be able to help choose the best one to include here as a good example as a reference

Comment thread sites/docs/src/content/interop/index.md Outdated
Comment thread sites/docs/src/content/interop/index.md
Comment thread sites/docs/src/content/interop/index.md Outdated
@kjxbyz

kjxbyz commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

I recall there being a concept called "direct native interop" (or something similar)—what happened to it? Why hasn't there been any news about it lately?

Edit

https://youtu.be/PRo98xNvyjQ?is=SOVR6XhVHH3MW8-3

@goderbauer goderbauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's still outdated verbiage in one places on the website, e.g.
https://docs.flutter.dev/platform-integration/android/call-jetpack-apis says:

In the coming months, the Dart team hopes to make this process easier with direct support for calling native APIs using the FFI approach...

Can we update that as well as part of this update?


When you use FFIgen or JNIgen to generate Dart bindings,
the generated code doesn't automatically convert Dart objects
like `String` or `List` into native formats.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dart:ffi doesn't directly relate to converting strings and lists into native ObjC or Java formats (there are utils in package:ffi to convert Dart strings to C strings, but that's a bit different), so this sentence is a bit misleading. Might be better to remove this sentence (or the whole paragraph)?

Dart memory is automatically garbage collected while native C memory is
manually managed, so use `dart:ffi` to bridge this gap.

The two most common scenarios when `dart:ffi` is needed are

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm. All the memory allocation and string conversion utils are in package:ffi, not dart:ffi. This whole section sounds like it's talking about package:ffi.


- **`dart:ffi`:** Built into the core Dart SDK.
It provides native representation types and lookup signatures.
- **`package:ffi`:** A required dependency for working with `dart:ffi`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite true that it's a required dependency. dart:ffi is required for doing FFI interop. package:ffi contains utils that are helpful in common C interop usecases.


FFI calls are synchronous and run on the thread on which they're called.
If you invoke a heavy or blocking C function on your Flutter app's
main UI thread, your app freezes or drops frames.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about: "your app may freeze or drop frames".

FFIgen wrappers enforce Dart static types,
but the underlying Objective-C object might have a different runtime subclass,
so Dart's `is` and `as` keywords won't work as expected.
Use `.isA()` and `.as()` instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


UI-related Objective-C calls must run on the iOS main platform thread.
Also, some types of callbacks can crash your app
if they're executed on the wrong thread.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JNI wrappers are Dart extension types that compile down to `JObject`
at runtime, so Dart's native `is` and `as` keywords don't check the Java
runtime type.
Use `x.isA(Foo.type)` and `x.as(Foo.type)` instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a hard limit of 50,000 active references.
Call `.release()` or use `.using()` blocks to prevent memory leaks.
Use `WeakReference` to break reference cycles between Dart and Java GCs
when implementing interfaces.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use [`runOnPlatformThread`][run-on-platform-thread] from `dart:ui`.
- Dart callbacks from Java run on the isolate that created them.
This can lead to deadlocks if a blocked Java thread waits for a blocked
Dart thread.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracking down JNI memory allocation bugs like `DoubleReleaseError`
and `UseAfterReleaseError` can be difficult.
Set `Jni.captureStackTraceOnRelease = true` to log stack traces
and help trace leaks.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants