JavaScript 的互操作

导入和导出 JS 函数

从 Rust 方面来看

在 JS 环境 中使用 wasm 时,从 Rust 导入和导出函数很简单: 它的工作方式与 C 完全相同

WebAssembly 模块定义了导入的一个系列,每个导入带有一个 模块名 和 一个导入名称。 但我们可以使用一个extern { ... }区块和 #[link(wasm_import_module)]来声明模块名, 目前 它默认为”env”。

导出只需要一个名称。 除了其他extern函数之外,WebAssembly 实例的线性内存默认导出为”memory”


# #![allow(unused_variables)]
#fn main() {
// 从 `mod`模块导入一个函数 `foo`
#[link(wasm_import_module = "mod")]
extern { fn foo(); }

// 导出 一个 Rust 函数 `bar`
#[no_mangle]
pub extern fn bar() { /* ... */ }
#}

由于 wasm 的有限值类型,这些函数必须仅在 原始数字类型上运行。

从 JS 方面来看

在 JS 中,wasm 二进制文件变成了 ES6 模块。

其中,线性内存的实例化和一组 JS 函数,一定是预期导入吻合的。 有关实例化的详细信息,请访问MDN

生成的 ES6 模块将包含从 Rust 导出的所有函数,现在可用作 JS 函数。

这里是整个设置的一个非常简单的例子。

超越数字

在 JS 中使用wasm时,wasm模块的内存与 JS 内存之间存在明显的分歧:

  • 每个wasm模块都有一个线性内存 (在本文档的顶部描述) ,它在实例化期间初始化。 JS 代码可以自由地读写这个内存

  • 相比之下,wasm代码没有直接访问 JS 对象。

因此,复杂的互操作以两种主要方式发生:

  • 将二进制数据复制或输出到wasm内存。 例如,这是一种String提供所有权的到 Rust 的方式。

  • 设置 JS 对象的显式”堆”,然后给出”地址”。 这允许wasm代码间接引用 JS 对象 (使用整数) ,并通过 调用导入的 JS 函数 对 这些对象 进行操作。

幸运的是,这个互操作故事非常适合通过通用的”bindgen”式框架进行处理: wasm-bindgen。 该框架可以自动编写 惯用 Rust 函数签名 映射 惯用 JS 函数 的