Fork me on GitHub

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

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

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

  通过分析 GitHub 上 Dart 代码的大量语料库,训练基于给定上下文的可能出现的成员的模型来实现的,这个模型由 TensorFlow Lite 驱动,可以用来预测开发人员正要编辑的代码,这个新特性称为 ML Complete。

  假设编写一个小程序,用来计算从当前时间到某一天的时间。使用 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 互操作支持的两种主要方案:

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

  调用基于 C 的操作系统 API

  调用 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();

  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"};

 

来自:
开源中国(ID: oschina2013)

作者:Johnson
原创文章,版权所有,转载请保留原文链接。