将类型传递给 wasm-bindgen
在 Rust/JS 类型之间进行转换时,最后要讨论的一个方面是如何实际传递此信息。#[wasm_bindgen]
宏正在运行 Rust 代码的句法(未解析)结构,然后负责生成 CLI 工具 wasm-bindgen
稍后读取的信息。
为了实现这一点,采用了略微非常规的方法。关于 Rust 代码结构的静态信息(目前)通过 JSON 序列化到 Wasm 可执行文件的自定义部分。其他信息,例如类型实际上是什么,由于诸如关联类型投影和 typedef 等原因,不幸的是,在编译器后期才知道。事实证明,我们还想将诸如 FnMut(String, Foo, &JsValue)
之类的“富”类型传递给 wasm-bindgen
CLI,而处理所有这些都非常棘手!
为了解决这个问题,#[wasm_bindgen]
宏会生成“描述导入或导出的类型签名的”**可执行函数**。这些可执行函数是 WasmDescribe
特性的全部内容
#![allow(unused)] fn main() { pub trait WasmDescribe { fn describe(); } }
尽管表面上很简单,但此特性实际上非常重要。当您编写如下导出时
#![allow(unused)] fn main() { #[wasm_bindgen] fn greet(a: &str) { // ... } }
除了上面我们讨论过的 JS 生成的垫片外,宏*还*会生成类似于以下内容:
#[no_mangle]
pub extern "C" fn __wbindgen_describe_greet() {
<dyn Fn(&str)>::describe();
}
或者换句话说,它生成了 describe
函数的调用。这样做,__wbindgen_describe_greet
垫片是对导入/导出的类型布局的程序化描述。这些描述在 wasm-bindgen
运行时执行!这些执行依赖于名为 __wbindgen_describe
的导入,该导入将一个 u32
传递给主机,并且在多次调用时有效地提供 Vec<u32>
。然后可以将此 Vec<u32>
重新解析为完全描述类型的 enum Descriptor
。
总而言之,这有点绕弯,但不应对生成的代码或运行时产生任何影响。所有这些描述符函数都从发出的 Wasm 文件中修剪掉了。