#wasm-module #reference #anyref #shim #resources #data

externref

为 WASM 模块提供低成本引用类型转换器

2 个不稳定版本

0.2.0 2023年6月3日
0.1.0 2022年10月29日

#296WebAssembly


用于 externref-cli

MIT/Apache

90KB
1.5K SLoC

为 WASM 模块提供低成本引用类型转换器

Build Status License: MIT OR Apache-2.0 rust 1.66+ required

文档: Docs.rs crate docs (main)

引用类型(即 externrefanyref)是宿主环境提供给 WASM 模块的一个不可见引用。这些引用不能在 WASM 代码中伪造,可以与任意宿主数据进行关联,因此是针对临时句柄(例如,数字句柄)的良好替代品。引用不能存储在 WASM 线性内存中;它们被限制在具有 externref 元素的栈和表中。

Rust 不支持原生的引用类型;没有方法可以产生一个带有 externref 作为参数或返回类型的导入/导出。如果启用了 externrefwasm-bindgen 将修补 WASM。这个库力求为通用的底层 WASM ABIs 实现同样的目标(wasm-bindgen 是针对浏览器宿主定制的)。

externref 使用案例

由于 externref 对模块来说是完全不可见的,使用它们的唯一方法是作为导入函数的参数将 externref 发送回宿主。根据函数语义,调用可能会或可能不会消耗 externref,可能会或可能不会修改底层数据(这不会反映在 WASM 函数签名中)。模块不能解引用 externref,因此,模块不能直接访问或修改引用背后的数据。实际上,模块甚至不能确定正在引用的数据类型。

这似乎大大限制了 externref 的实用性,但 externref 仍然很有用,例如,在宿主环境中模拟基于能力的安全性令牌或资源句柄。另一个潜在的用例是将复杂的数据封装起来,这些数据不适合通过 WASM API 边界传输(特别是如果数据形状可能随时间演变),或者如果必须从模块侧限制与数据的交互。

用法

将以下内容添加到您的 Crate.toml

[dependencies]
externref = "0.2.0"
  1. 在WASM模块中,使用Resource作为导入和/或导出函数的参数/返回结果,而不是使用externref。支持引用参数(包括可变引用)以及Option<_>包装器。
  2. 在导入/导出函数上添加#[externref]过程宏。
  3. 使用来自crate相应模块的模块处理器转换生成的WASM模块。

作为最终步骤的替代方案,有一个CLI应用程序可以处理WASM模块,但控制粒度稍低。

重要。处理器应在WASM优化工具(如binaryen的wasm-opt)之前运行。

示例

在针对WASM的代码中使用#[externref]宏和Resource

use externref::{externref, Resource};

// Two marker types for different resources.
pub struct Arena(());
pub struct Bytes(());

#[cfg(target_arch = "wasm32")]
#[externref]
#[link(wasm_import_module = "arena")]
extern "C" {
    // This import will have signature `(externref, i32) -> externref`
    // on host.
    fn alloc(arena: &Resource<Arena>, size: usize) 
        -> Option<Resource<Bytes>>;
}

// Fallback for non-WASM targets.
#[cfg(not(target_arch = "wasm32"))]
unsafe fn alloc(_: &Resource<Arena>, _: usize) 
    -> Option<Resource<Bytes>> { None }

// This export will have signature `(externref) -> ()` on host.
#[externref]
#[export_name = "test_export"]
pub extern "C" fn test_export(arena: &Resource<Arena>) {
    let bytes = unsafe { alloc(arena, 42) }.expect("cannot allocate");
    // Do something with `bytes`...
}

有关更多使用示例和实现细节,请参阅crate文档。

项目状态 🚧

实验性;处理器可能在某些边缘情况下产生无效的WASM(如果发生这种情况,请作为问题报告)。

许可证

根据您的选择,在Apache License, Version 2.0MIT许可证下许可。

除非您明确表示,否则您提交给externref的任何贡献(根据Apache-2.0许可证定义),都将按上述方式双重许可,不附加任何额外条款或条件。

依赖关系

~0–720KB
~14K SLoC