我有一个板条箱lib
,里面有很多structs和impl。然后我有另一个名为web
的,它将使核心lib
可移植到web。还有api
,以防我希望应用程序位于服务器端。
myproject-api
myproject-lib
myproject-web
我不想只在web
项目中将所有wasm
依赖项添加到lib
,并将主库的部分内容公开到web。在myproject-web
中myproject-lib
中定义的结构是否可以#[wasm_bindgen]
?
不直接。#[wasm_bindgen]
属性依赖于能够解析结构和impl以生成绑定。您必须为要绑定的属性创建包装器类型和函数。
假设你的myproject-lib
看起来像:
pub struct MyStruct {
pub foo: i32,
}
impl MyStruct {
pub fn bar(&self) {
// do something
}
}
绑定将在myproject-web
中实现,如:
use myproject_lib::*;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(js_name = MyStruct)]
pub struct MyStructWrapper(MyStruct);
#[wasm_bindgen(js_class = MyStruct)]
impl MyStructWrapper {
#[wasm_bindgen(getter)]
pub fn foo(&self) -> i32 {
self.0.foo
}
#[wasm_bindgen(setter)]
pub fn set_foo(&mut self, value: i32) {
self.0.foo = value;
}
pub fn bar(&self) {
self.0.bar();
}
}
正如你所看到的,每件事都做得非常明确。
- 使用
js_name
和js_class
封装原始结构并使用原始名称导出 - 列出并实现公共字段的getter和setter
- 向原始结构添加简单的转发函数
我认为更广泛使用的方法是将绑定添加到原始库中,但仅由一个功能启用。这避免了大量重复,实现起来不那么麻烦,并确保绑定始终同步。
添加"wasm"
功能,将wasm-bindgen
添加为Cargo.toml
:中的选择加入依赖项
[features]
wasm = ["wasm-bindgen"]
[dependencies]
wasm-bindgen = { version = "X.X.X", optional = true }
然后,您可以使用cfg
和cfg_attr
仅在功能启用时启用wasm_bindgen
属性:
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
#[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct MyStruct {
pub foo: i32,
}
#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl MyStruct {
pub fn bar(&self) {
// do something
}
}