2 个不稳定版本
0.2.0 | 2023年6月3日 |
---|---|
0.1.0 | 2022年10月29日 |
#296 在 WebAssembly
90KB
1.5K SLoC
为 WASM 模块提供低成本引用类型转换器
引用类型(即 externref
或 anyref
)是宿主环境提供给 WASM 模块的一个不可见引用。这些引用不能在 WASM 代码中伪造,可以与任意宿主数据进行关联,因此是针对临时句柄(例如,数字句柄)的良好替代品。引用不能存储在 WASM 线性内存中;它们被限制在具有 externref
元素的栈和表中。
Rust 不支持原生的引用类型;没有方法可以产生一个带有 externref
作为参数或返回类型的导入/导出。如果启用了 externref
,wasm-bindgen
将修补 WASM。这个库力求为通用的底层 WASM ABIs 实现同样的目标(wasm-bindgen
是针对浏览器宿主定制的)。
externref
使用案例
由于 externref
对模块来说是完全不可见的,使用它们的唯一方法是作为导入函数的参数将 externref
发送回宿主。根据函数语义,调用可能会或可能不会消耗 externref
,可能会或可能不会修改底层数据(这不会反映在 WASM 函数签名中)。模块不能解引用 externref
,因此,模块不能直接访问或修改引用背后的数据。实际上,模块甚至不能确定正在引用的数据类型。
这似乎大大限制了 externref
的实用性,但 externref
仍然很有用,例如,在宿主环境中模拟基于能力的安全性令牌或资源句柄。另一个潜在的用例是将复杂的数据封装起来,这些数据不适合通过 WASM API 边界传输(特别是如果数据形状可能随时间演变),或者如果必须从模块侧限制与数据的交互。
用法
将以下内容添加到您的 Crate.toml
[dependencies]
externref = "0.2.0"
- 在WASM模块中,使用
Resource
作为导入和/或导出函数的参数/返回结果,而不是使用externref
。支持引用参数(包括可变引用)以及Option<_>
包装器。 - 在导入/导出函数上添加
#[externref]
过程宏。 - 使用来自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.0或MIT许可证下许可。
除非您明确表示,否则您提交给externref
的任何贡献(根据Apache-2.0许可证定义),都将按上述方式双重许可,不附加任何额外条款或条件。
依赖关系
~0–720KB
~14K SLoC