Ole*_*Cat 7 javascript rust webassembly wasm-bindgen
假设我在 Rust 代码中有以下定义:
#[wasm_bindgen]
pub struct RustType {
foo: usize
}
#[wasm_bindgen]
impl RustType {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self { foo: 100 }
}
}
#[wasm_bindgen]
pub fn print_addr(obj: &RustType) {
console_log!("rust addr = {}", obj as *const _ as u32);
}
Run Code Online (Sandbox Code Playgroud)
JS 代码创建一个实例RustType并将其传递给print_addr函数:
var obj = new RustType();
print_addr(obj);
Run Code Online (Sandbox Code Playgroud)
修改生成的print_addr函数后index_bg.js如下:
export function print_addr(obj) {
_assertClass(obj, RustType);
console.log("js addr = ", obj.ptr); // <== added this line
if (obj.ptr === 0) {
throw new Error('Attempt to use a moved value');
}
wasm.print_addr(obj.ptr);
}
Run Code Online (Sandbox Code Playgroud)
在开发控制台中我得到以下输出:
js addr = 1114120
rust addr = 1114124
Run Code Online (Sandbox Code Playgroud)
问题是为什么 Rust 指针和 JS 指针的值不同?另外根据我的观察,Rust 指针和 JS 指针之间的差异始终等于 4。为什么会这样呢?
如果您查看将结构导出到 JS,在页面下方您可以看到某些函数的生成代码。看起来相关的一个是:
#[export_name = "foo_new"]
pub extern "C" fn __wasm_bindgen_generated_Foo_new(arg0: i32) -> u32
let ret = Foo::new(arg0);
Box::into_raw(Box::new(WasmRefCell::new(ret))) as u32
}
Run Code Online (Sandbox Code Playgroud)
所以我们有一个通过 Box 的指针,nbd,但是您可以看到Foo(暴露给 JavaScript 的结构)被包装在 a 中WasmRefCell,这是RefCell 的供应版本,但更重要的是具有两个字段的结构:
pub struct WasmRefCell<T> {
borrow: Cell<usize>,
value: UnsafeCell<T>,
}
Run Code Online (Sandbox Code Playgroud)
这T是 Rust 类型,因此在 Rust 类型内部您可以看到该地址,但是提供给 Javascript 的是 的地址WasmRefCell,这意味着它可能Cell<usize>是源中结构体之前的的地址:rustc 不保证它将匹配源布局(除非您用 注释结构repr(C)),但在这里它没有理由接触任何东西,所以它不匹配也就不足为奇了。
WebAssembly 是 32 位架构,因此size_of::<usize>() == 4,返回给 JS 的指针位于 Rust 结构内部可见位置之前 4 个字节。量子ED。
| 归档时间: |
|
| 查看次数: |
963 次 |
| 最近记录: |