如何在JS文件中使用Rust通过wasm_bindgen导出的struct结构体?
问题原因
默认wasm_bindgen导出的Rust结构体不会自动暴露内部字段,JS侧拿到的是指向Wasm线性内存的不透明引用,因此直接打印只会显示底层指针标识,无法直接访问内部的x、y值。
解决方法
方法1:为字段添加getter/setter(最常用,保留Wasm侧实例功能)
只需要在结构体字段上添加#[wasm_bindgen(getter, setter)]属性,即可让JS侧直接读写对应字段:
#[wasm_bindgen] pub struct Point { // 暴露x字段的读写能力 #[wasm_bindgen(getter, setter)] pub x: i32, // 暴露y字段的读写能力 #[wasm_bindgen(getter, setter)] pub y: i32, } #[wasm_bindgen] impl Point { #[wasm_bindgen(constructor)] pub fn new(x: i32, y: i32) -> Point { Point { x, y } } }
修改后JS侧即可正常访问字段:
let p = new Point(23, 34); console.log(p.x); // 输出 23 console.log(p.y); // 输出 34 // 如果需要完整的对象格式,可以手动构造: const obj = { x: p.x, y: p.y, __proto__: Point.prototype }; console.log(obj); // 输出 {x:23, y:34} 且携带Point原型
方法2:Rust侧直接返回符合要求的JS对象
如果希望直接从Rust侧得到带原型的标准JS对象,可以添加to_js_obj方法手动构造:
首先在Cargo.toml中添加依赖:
[dependencies] js-sys = "0.3"
修改Rust代码:
use js_sys::{Object, Reflect}; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct Point { x: i32, y: i32, } #[wasm_bindgen] impl Point { #[wasm_bindgen(constructor)] pub fn new(x: i32, y: i32) -> Point { Point { x, y } } pub fn to_js_obj(&self) -> JsValue { let obj = Object::new(); // 写入x、y属性 Reflect::set(&obj, &"x".into(), &self.x.into()).unwrap(); Reflect::set(&obj, &"y".into(), &self.y.into()).unwrap(); // 绑定Point原型 let point_constructor = Reflect::get(&js_sys::global(), &"Point".into()).unwrap(); let point_proto = Reflect::get(&point_constructor, &"prototype".into()).unwrap(); Object::set_prototype_of(&obj, &point_proto); obj.into() } }
JS侧调用:
let p = new Point(23, 34); let jsObj = p.to_js_obj(); console.log(jsObj); // 直接输出 {x:23, y:34} 且携带Point原型
方法3:用Serde自动序列化(适合纯数据结构体)
如果你的Point是纯数据结构体,不需要在Rust侧保留实例引用,可以启用Serde自动序列化转成JS对象:
首先修改Cargo.toml添加依赖:
[dependencies] wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } serde = { version = "1.0", features = ["derive"] }
修改Rust代码:
use serde::{Serialize, Deserialize}; use wasm_bindgen::prelude::*; #[wasm_bindgen(serde)] #[derive(Serialize, Deserialize)] pub struct Point { pub x: i32, pub y: i32, } #[wasm_bindgen] impl Point { #[wasm_bindgen(constructor)] pub fn new(x: i32, y: i32) -> Point { Point { x, y } } }
修改后new Point直接返回标准JS对象,自带x、y属性。
内容的提问来源于stack exchange,提问作者akshay karande
相关产品推荐
相关产品推荐

