Dart 2.5 发布,支持 Dart 与 C 相互调用

Dart 2.5 已经发布了,其中包括两个主要预览新特性:机器学习(ML)驱动的代码补全和 dart:ffi 外部函数接口,用于直接从 Dart 调用 C 代码。Dart 2.5 还改进了对常量表达式的支持。具体如下:

ML Complete,按机器学习排序的代码补全

通过分析 GitHub 开放源代码 Dart 代码的大量语料库,根据给定的上下文训练可能出现的成员事件的模型。这个模型由 TensorFlow Lite 驱动,可以用来预测开发人员正要编辑的下一个符号,这个新特性称为 ML Complete。下面是一个使用 Flutter 框架开发新 MyHome 小部件的示例:

假设编写一个小程序,用来计算从当前时间到某一天的时间。使用 ML Complete,如下所示(第一张图)。首先,它能够根据变量名称为 now 自动提供 DateTime.Now() 补全 。接下来,定义变量名 tomorrow,使用 add(…) 方法。在非 ML Complete 中(第二张图),必须手动开始输入 Datetime 才会有提示补全,而且 add() 方法在补全提示的列表中的位置要低。

ML Complete 可以在所有支持 Dart 的编辑器中使用,包括 Android Studio、IntelliJ 和 VS Code等。由于该特性仍出于预览阶段,若要试用可在 Flutter dev channel 和 Dart dev channel 版。

dart:ffi 外部函数接口

目前,直接从 Dart 调用 C 的支持仅限于使用原生扩展深入集成到 Dart VM 中,或者 Flutter 应用程序可以间接调用 C,通过使用 Platform Channel 调用主机,在那里调用 C,这是一个不受欢迎的双重间接。

Dart-C 互操作支持的两种主要方案:

  1. 在主机操作系统(OS)上调用基于 C 的系统 API
  2. 为单个操作系统或跨平台调用基于 C 的库

调用基于 C 的操作系统 API

扫描二维码关注公众号,回复: 7261544 查看本文章

调用 Linux 命令 system,该命令允许执行任何系统命令,传递给它的参数实际是传递给  shell/terminal,并在其运行。下面是这个命令的 C 头文件:

// C header: int system(const char *command) in stdlib.h

任何互操作机制的难点在于处理两种语言在语义上的差异。对于 dart:ffi,Dart 代码需要表示两件事:

  • C 函数及其参数和返回类型的类型
  • 对应的 Dart 函数及其类型
// C header typedef:
typedef SystemC = ffi.Int32 Function(ffi.Pointer<Utf8> command);

// Dart header typedef:
typedef SystemDart = int Function(ffi.Pointer<Utf8> command);

然后,需要加载库并查找要调用的函数,如何做到这一点取决于操作系统;在本例中,使用的是 MacOS:

// Load `stdlib`. On MacOS this is in libSystem.dylib.
final dylib = ffi.DynamicLibrary.open('/usr/lib/libSystem.dylib');

// Look up the system function.
final systemP = dylib.lookupFunction<SystemC, SystemDart>('system');

接下来,使用与特定操作系统相关的编码对字符串参数进行编码,调用函数,并再次释放参数内存:

// Allocate a pointer to a Utf8 array containing our command.
final cmdP = Utf8.toUtf8('open http://dart.dev');

// Invoke the command.
systemP(cmdP);

// Free the pointer.
cmdP.free();

此代码执行系统命令,导致系统默认浏览器打开 dart.dev:

调用基于 C 的框架和组件

Dart 的第二个核心用途是调用基于 C 的框架和组件。如上的示例,它使用 TensorFlow Lite,一个基于 C 的 API,使用 Dart:ffi 允许在需要提供代码完成的所有操作系统上运行 TensorFlow,并具有本机 TensorFlow 实现的高性能。

目前 dart:ffi 出于预览阶段,所以还会有一些限制。

另外,从 Dart 2.5 开始,支持更多的方法来定义常量表达式,包括强制转换以及在 Dart 2.3 中提供的新的控制流和集合扩展特性:

const Object i = 3;
const list = [i as int];
const set = {if (list is List<int>) ...list};
const map = {if (i is int) i: "int"};

详情见发布说明

猜你喜欢

转载自www.oschina.net/news/109799/dart-2-5-released