#[wasm_bindgen] public 结构和函数是否可以在另一个 crate 中定义?
Is it possible to #[wasm_bindgen] public structs and functions defined in another crate?
我有一个板条箱 lib
,其中包含大量结构和 impl。然后我有另一个名为 web
的,它将使核心 lib
可移植到 Web。还有 api
以防我希望该应用程序是服务器端的。
myproject-api
myproject-lib
myproject-web
我不想要的是仅在 web
项目中将所有 wasm
依赖项添加到 lib
,并将主库的部分内容公开到 Web。是否可以 #[wasm_bindgen]
myproject-lib
中定义的结构 myproject-web
?
不直接。 #[wasm_bindgen]
属性依赖于能够解析 struct 和 impls 以生成绑定。您必须为要绑定到的属性创建包装器类型和函数。
假设你的 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(getter)]
pub fn set_foo(&mut self, value: i32) {
self.0.foo = value;
}
pub fn bar(&self) {
self.0.bar();
}
}
如您所见,一切都做得非常明确。
- 封装原始结构并使用
js_name
and js_class
以原始名称导出
- 为 public 个字段列出并实施 getters and setters
- 在原始结构中添加简单的转发函数。
我相信更广泛使用的方法是将绑定添加到原始库中,但仅由功能启用。这避免了很多重复,实现起来更容易,并确保绑定始终同步。
添加 "wasm"
feature 将 wasm-bindgen
添加为 Cargo.toml
中的依赖项:
[features]
wasm = ["wasm-bindgen"]
[dependencies]
wasm-bindgen = { version = "X.X.X", optional = true }
然后您可以使用cfg
and 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
}
}
我有一个板条箱 lib
,其中包含大量结构和 impl。然后我有另一个名为 web
的,它将使核心 lib
可移植到 Web。还有 api
以防我希望该应用程序是服务器端的。
myproject-api
myproject-lib
myproject-web
我不想要的是仅在 web
项目中将所有 wasm
依赖项添加到 lib
,并将主库的部分内容公开到 Web。是否可以 #[wasm_bindgen]
myproject-lib
中定义的结构 myproject-web
?
不直接。 #[wasm_bindgen]
属性依赖于能够解析 struct 和 impls 以生成绑定。您必须为要绑定到的属性创建包装器类型和函数。
假设你的 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(getter)]
pub fn set_foo(&mut self, value: i32) {
self.0.foo = value;
}
pub fn bar(&self) {
self.0.bar();
}
}
如您所见,一切都做得非常明确。
- 封装原始结构并使用
js_name
andjs_class
以原始名称导出
- 为 public 个字段列出并实施 getters and setters
- 在原始结构中添加简单的转发函数。
我相信更广泛使用的方法是将绑定添加到原始库中,但仅由功能启用。这避免了很多重复,实现起来更容易,并确保绑定始终同步。
添加 "wasm"
feature 将 wasm-bindgen
添加为 Cargo.toml
中的依赖项:
[features]
wasm = ["wasm-bindgen"]
[dependencies]
wasm-bindgen = { version = "X.X.X", optional = true }
然后您可以使用cfg
and 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
}
}