Dart与其他语言的互操作理解 FFI/JNI/WASM

ffi和jni的理解

  • 通过 ffi 调用 C 语言的API,可以实现全平台(除Web)的支持;
  • 通过 jni 调用 Java/Kotlin API,可以实现Android、Windows、macOS 和 Linux的支持(是的,不包括iOS平台,目前jni还是实验性质)
  • 通过 ffi 可以调用 iOS、MacOS 上 OC/Swift API 代码,可以替代通道调用;
  • 通过 jni 可以调用 Android SDK API 代码,可以替代通道调用;

ffi和jni的应用

  • 例如实现一个编解码库,仅依赖C语言API,通过FFI可以实现对Android、iOS、Macos、Widnows、Linux的支持,写一份C代码就行了
  • 如果调用iOS上的SDK,获取屏幕、电量等API,可以通过 ffi 实现(channel也可以实现)
  • 如果调用Android上的SDK,获取屏幕、电量等API,可以通过 jni 实现(channel也可以实现)

ffi和ffigen

jni和jnigen

  • package:jni 是支持库,提供的通用基础结构;
  • package:jnigen 是代码生成器,jnigen生成两个绑定,通过 JNI 调用 Java 方法的 C 绑定,以及通过 FFI 调用这些 C 包装器的 Dart 绑定。

Dart和Web

  • 期待Dart下一代的架构设计,Dart和WebAssembly的互操作结合;

C interop using dart:ffi

Dart 的移动端、命令行和服务端应用所运行的 Dart 原生平台,==均可以使用 dart:ffi 库调用原生的 C 语言 API==,用于读、写、分配和销毁原生内存。 FFI 指的是 外部函数接口。类似的术语包括 原生接口 和 语言绑定。

原理是通过CMake,构建 C 代码库,生成动态库包括 libhello.dylib(仅 macOS)、 libhello.dll(仅 Windows)或 libhello.so(仅 Linux),然后通过 dart:ffi API 实现dart与c的调用。

Dart mobile, command-line, and server apps running on the Dart Native platform can use the dart:ffi library to call native C APIs, and to read, write, allocate, and deallocate native memory. FFI stands for foreign function interface. Other terms for similar functionality include native interface and language bindings.

API documentation is available in the dart:ffi API reference.

Objective-C and Swift interop using package:ffigen

Dart 的移动端、命令行和服务器应用 在 Dart Native 平台上运行,==在 macOS 或 iOS 上==, 可以使用和打包:ffigen 来调用 Objective-C 和 Swift API。dart:ffi

注意:此互操作功能是实验性的,并 积极发展

Dart mobile, command-line, and server apps running on the Dart Native platform, on macOS or iOS, can use dart:ffi and package:ffigen to call Objective-C and Swift APIs.

dart:ffi允许 Dart 代码与本机 C API 交互。 Objective-C基于C并兼容C, 因此,可以仅使用Objective-C API进行交互。 但是,这样做涉及大量样板代码, 因此您可以使用自动生成 给定 Objective-C API 的 Dart FFI 绑定。 要了解有关 FFI 和直接与 C 代码接口的更多信息, 请参阅 C 互操作指南。dart:ffi package:ffigen

dart:ffi allows Dart code to interact with native C APIs. Objective-C is based on and compatible with C, so it is possible to interact with Objective-C APIs using only dart:ffi. However, doing so involves a lot of boilerplate code, so you can use package:ffigen to automatically generate the Dart FFI bindings for a given Objective-C API. To learn more about FFI and interfacing with C code directly, see the C interop guide.

你可以为 Swift API 生成 Objective-C 标头, 允许并与 Swift 交互。dart:ffi package:ffigen

You can generate Objective-C headers for Swift APIs, allowing dart:ffi and package:ffigen to interact with Swift.

Java interop using package:jnigen

Dart 移动、命令行和服务器应用 在 Dart Native 平台上运行,在 ==Android、Windows、macOS 和 Linux== 可以使用 package:jni 和 package:jnigen 来调用 Java 和 Kotlin API。

Dart mobile, command-line, and server apps running on the Dart Native platform, on Android, Windows, macOS, and Linux can use package:jni and package:jnigen to call Java and Kotlin APIs.

注意:此互操作功能是实验性的,并 积极发展

package:jni 允许 Dart 代码交互 通过 JNI 使用 Java。 但是,这样做涉及大量样板代码, 因此您可以使用自动生成 给定 Java API 的 Dart 绑定。package:jnigen

package:jni allows Dart code to interact with Java through JNI. However, doing so involves a lot of boilerplate code, so you can use to automatically generate the Dart bindings for a given Java API.package:jnigen

您可以将 Kotlin 编译为 Java 字节码,从而也可以为 Kotlin 生成绑定。package:jnigen

You can compile Kotlin to Java bytecode, allowing to generate bindings for Kotlin as well.package:jnigen

参考:

  • Architecture-&-Design-Notes
  • FFIgen + JNIgen pedometer
  • JNIGen: An Easy Way to Access Platform APIs

JavaScript interoperability

Dart web 平台支持通过 package:js 和 JavaScript 交互

The Dart web platform supports calling JavaScript using the js package, also known as package:js.

For help using the js package, see the following:

  • Documentation for the js package:
    • pub.dev site page
    • API reference
  • Packages that use the js package:
    • sass is an example of a more unusual use case: providing a way for JavaScript code to call Dart code.

下一代的JS互操作设计

更看好下一代的JS互操作设计,从 Dart 编译到 WebAssembly,也可以进一步优化 Web 端的速度和代码体积。

支持未来 JS 互操作的许多功能 准备从 Dart 版本 2.19 开始进行试验。 这些功能支持现有生产 和开发网络编译器, 以及Dart正在进行的Wasm编译器(dart2wasm)。

WebAssembly是什么?

WebAssembly(又名wasm)是一种高效的,低级别的编程语言。 它让我们能够使用JavaScript以外的语言(例如C,C ++,Rust或其他)编写程序,然后将其编译成WebAssembly,进而生成一个加载和执行速度非常快的Web应用程序。

wasm只是一个字节码标准,人们可以基于这个标准开发高级语言。类似jvm一样,很多语言可以编译成jvm字节码,从而使用jvm平台。wasm出现的意义是使用其他语言开发web app成为可能

WebAssembly的优势:

  • 更好的性能:WebAssembly 在两个方面提供了增强的性能,即启动速度和吞吐量。缩小的 JavaScript 需要被解析、解释、编译和优化。另一方面,wasm 更紧凑,并且由于其简洁的设计,二进制格式允许更快的解析和快速优化。
  • 便携且安全:它独立于平台、独立于硬件和独立于语言,它不对设备或浏览器没有任何特殊要求,这增强了其便携性,代码在内存安全的沙盒环境中进行验证和执行,可以防止安全漏洞和数据损坏。
  • 集成遗留库:如果应用程序使用 C/C++ 或任何其他兼容语言,WebAssembly 可以轻松地将代码或桌面应用程序可用于 Web。通常使用两个库;用于 Rust 的 wasm-pack 和用于 C/C++ 的 Emscripten。

WebAssembly虽然可以实现一套VM环境,但是不会取代JS,WASM应该作为JS的扩展而存在,由于JS的性能有限WASM可以实现一些高性能组件。比如:编码工具,图像音频处理,数据分析等。