Repository navigation
Conversation
- 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
|
Staged preview of the updated docs.flutter.dev site (updated for commit fb5205b): https://flutter-docs-prod--docs-pr13995-native-interop-eap-ihm0amds.web.app |
|
/gemini review |
There was a problem hiding this comment.
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.
| Watch out for two common scenarios: | ||
|
|
||
| - Calling platform APIs that must run on the platform thread. | ||
| Use `runOnPlatformThread` from `dart:ui`. |
There was a problem hiding this comment.
In Flutter, there is no top-level function or direct class named runOnPlatformThread in the dart:ui library. To run a task on the platform thread, you should use PlatformDispatcher.instance.scheduleOnPlatformThread (introduced in newer Flutter versions) or coordinate with platform channels / native bindings. Please update this reference to the correct API to avoid confusing developers.
| Use `runOnPlatformThread` from `dart:ui`. | |
| Use `PlatformDispatcher.instance.scheduleOnPlatformThread` from `dart:ui`. |
References
- Ensure correct instructions, commands, API names, or expected results are documented. (link)
sfshaza2
left a comment
There was a problem hiding this comment.
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.
| For desktop-specific guidance on calling system APIs—including wrapper | ||
| packages like [`package:win32`]({{site.pub-pkg}}/win32) and | ||
| [Canonical's Linux packages]({{site.pub}}/publishers/canonical.com/packages)—see | ||
| [Canonical's Linux packages]({{site.pub}}/publishers/canonical.com/packages)—refer to |
There was a problem hiding this comment.
It's true that we used to use the HTML "—" extensively, but these days you can just paste the character itself into the text.
| The `dart:ffi` (Foreign Function Interface) library is a core Dart SDK library | ||
| that provides the low-level APIs to call C-ABI functions from Dart. | ||
|
|
||
| Rather than a code generation tool like [Pigeon](/interop/pigeon), |
There was a problem hiding this comment.
| Rather than a code generation tool like [Pigeon](/interop/pigeon), | |
| Rather than code generation tools like [Pigeon](/interop/pigeon), |
This is listing multiple tools, right? If not, the sentence should be rephrased.
| for native arguments, and you must manually free that memory when done. | ||
| This helps avoid memory leaks. |
There was a problem hiding this comment.
| for native arguments, and you must manually free that memory when done. | |
| This helps avoid memory leaks. | |
| for native arguments, and you must manually free that memory when done | |
| to prevent memory leaks. |
The text "That helps to avoid..." is a bit vague. It makes me wonder what else I've done to introduce a memory leak.
|
|
||
| ## Concurrency in Flutter | ||
|
|
||
| FFI calls are synchronous and run on the thread they are called on. |
There was a problem hiding this comment.
| FFI calls are synchronous and run on the thread they are called on. | |
| FFI calls are synchronous and run on the thread on which they are called. |
I don't usually complain about dangling participles, but this one bothered me.
| :::note | ||
| Direct Swift interop is in experimental support. | ||
| ::: |
There was a problem hiding this comment.
Can you give an idea of how likely it is to change or how soon? I'd say just a tad more here. Such as "... and is likely to change."
|
|
||
| ## Developer flow | ||
|
|
||
| The developer experience with Pigeon follows a structured cycle: |
There was a problem hiding this comment.
Make this text active, please!
| and produces the necessary code for both Dart and your target native platform. | ||
|
|
||
| :::note | ||
| If you're using the Pigeon with native interop communication option, |
There was a problem hiding this comment.
| If you're using the Pigeon with native interop communication option, | |
| If you're using Pigeon with the native interop communication option, |
"...the Pigeon.."??
| refer to the [native interop guide][pigeon-native-guide]. | ||
| ::: | ||
|
|
||
| After the code is generated, you implement the generated native interfaces |
There was a problem hiding this comment.
| After the code is generated, you implement the generated native interfaces | |
| After the code is generated, implement the generated native interfaces |
I notice that the text often uses "...you ...". Most of the time, the "you" just isn't necessary.
| in the platform-specific directories of your Flutter project | ||
| (such as `android/`, `ios/`, or `macos/`) | ||
| and register them with the Flutter engine. | ||
| Finally, you call the generated Dart classes from your Flutter app, |
There was a problem hiding this comment.
| Finally, you call the generated Dart classes from your Flutter app, | |
| Finally, call the generated Dart classes from your Flutter app, |
For example...
|
|
||
| ### Inheritance | ||
|
|
||
| Pigeon does not support complex inheritance. |
There was a problem hiding this comment.
| Pigeon does not support complex inheritance. | |
| Pigeon doesn't support complex inheritance. |
You know, this insistence on avoiding contractions just isn't necessary. Studies show that, in verbal communication, avoiding contractions can be clearer, but not so much in written communication. This is really an old school idea that hasn't proven out.
sfshaza2
left a comment
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
Just a couple little clarifications
| ### (Pigeon with platform channels only) Async errors | ||
|
|
||
| For `@async` methods, native code must return errors through the provided | ||
| callback. |
There was a problem hiding this comment.
Since Pigeon 28.0.0, @async generates suspend functions in Kotlin and async throws methods in Swift even when using platform channels (where native code throws FlutterError or PigeonError directly rather than using a callback). Completion callbacks are now only generated for @asyncCallback methods (for platform channels) or in the Java, Objective-C, C++, and GObject generators.
| | Target language | Direct interop | Pigeon | | ||
| | --- | --- | --- | | ||
| | **C** | [FFIgen](/interop/ffigen) | Not recommended. Supported with platform channels, but not maintained by the Flutter team. | | ||
| | **C++ with `extern "C"`** | [FFIgen](/interop/ffigen) | (Refer to C) | | ||
| | **C++ without `extern "C"`** | FFIgen (not yet supported) | Supported with platform channels, but not maintained by the Flutter team. | | ||
| | **Rust with `extern "C"`** | [FFIgen](/interop/ffigen) | (Refer to C) | | ||
| | **Rust without `extern "C"`** | [Flutter Rust Bridge][frb] | Not supported | | ||
| | **Go with `extern "C"`** | [FFIgen](/interop/ffigen) | (Refer to C) | | ||
| | **Go without `extern "C"`** | Not supported | Not supported | | ||
| | **Java** | [JNIgen](/interop/jnigen) | Supported through Kotlin | | ||
| | **Kotlin** | [JNIgen](/interop/jnigen) | Supported (recommended) | | ||
| | **Objective-C** | [FFIgen](/interop/ffigen) | Supported through Swift | | ||
| | **Swift without Obj-C compatibility annotations** | [`package:swiftgen`][swiftgen-pub] (experimental) | Supported (recommended) | |
There was a problem hiding this comment.
Two clarifications on the Pigeon column here:
- Pigeon's C (GObject on Linux) and C++ (Windows) platform-channel generators in
flutter/packagesare maintained by the Flutter team for desktop plugins, though they only support platform-channels. - For Java and Objective-C, "Supported through Kotlin" / "Supported through Swift" applies to Pigeon with native interop, whereas Pigeon with platform channels also includes direct Java (
JavaOptions) and Objective-C (ObjcOptions) generators.
| :::note | ||
| If you're using the Pigeon with native interop communication option, | ||
| set `appDirectory`, `swiftOptions: SwiftOptions(useFfi: true)`, and | ||
| `kotlinOptions: KotlinOptions(useJni: true)` in the `@ConfigurePigeon` | ||
| section of your Pigeon definition file. | ||
| For complete prerequisites and build configuration, | ||
| refer to the [native interop guide][pigeon-native-guide]. | ||
| ::: | ||
|
|
||
| After the code is generated, you implement the generated native interfaces | ||
| in the platform-specific directories of your Flutter project | ||
| (such as `android/`, `ios/`, or `macos/`) | ||
| and register them with the Flutter engine. | ||
| Finally, you call the generated Dart classes from your Flutter app, | ||
| or invoke the generated native APIs to call back into your Dart code. |
There was a problem hiding this comment.
A few helpful details from native_interop_guide.md that could save readers from common setup errors when using Pigeon with native interop:
- In
@ConfigurePigeon,SwiftOptionsalso takesffiModuleName(for example,SwiftOptions(useFfi: true, ffiModuleName: 'Runner')). - On the Dart side, callers must instantiate the generated host API using
<MyApi>.createWithNativeInteropApi()(since the default<MyApi>()constructor uses platform channels). - Under Constraints and limitations, we could note that
@ProxyApi, and@TaskQueueare only supported with platform channels, but it's probably not worth mentioning.
| between Dart and host platforms. | ||
| To learn how to use Pigeon, define API contracts, and choose between | ||
| native interop and platform channels, | ||
| refer to the dedicated [Pigeon guide](/interop/pigeon). |
There was a problem hiding this comment.
(Note regarding lines 1426–1430 of sites/docs/src/content/platform-integration/platform-channels.md)
Since the [Pigeon][] reference in the #pigeon section was replaced with [Pigeon guide](/interop/pigeon), the [Pigeon]: {{site.pub-pkg}}/pigeon link definition on line 1428 is now unused and can be removed.
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:/interop): Decision tree (Mermaid flowchart and step-by-step walkthrough), packaging options, tool comparison matrix, and 3-layer interop architecture./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./interop/ffigen): Covers generating C, Objective-C, and Swift bindings withtool/ffigen.dart, developer workflow, examples, and platform/runtime considerations./interop/jnigen): Covers generating Java and Kotlin bindings on Android withtool/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)./interop/bind-native-code): Moved from/platform-integration/bind-native-codewith a 301 redirect infirebase.json./platform-integration/platform-channels): Updated to link to the new Native interop overview and dedicated Pigeon guide.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
of 80 characters or fewer.