Not directly. The #[wasm_bindgen]
attribute relies on being able to parse the struct and impls in order to generate the bindings. You would have to create wrapper types and functions for the attribute to bind to.
Say your myproject-lib
looks like:
pub struct MyStruct {
pub foo: i32,
}
impl MyStruct {
pub fn bar(&self) {
// do something
}
}
The bindings would be implemented in myproject-web
like:
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();
}
}
As you can see, everything is done very explicitly.
- encapsulate the original struct and export it with the original name using
js_name
and js_class
- list out and implement getters and setters for public fields
- add simple forwarding functions to the original struct.
I believe the more widely-used method is to add the bindings to the original library but only enabled by a feature. This avoids much duplication, is less of a headache to implement, and ensures the bindings are always in-sync.
Add a "wasm"
feature that adds wasm-bindgen
as an opt-in a dependency in your Cargo.toml
:
[features]
wasm = ["wasm-bindgen"]
[dependencies]
wasm-bindgen = { version = "X.X.X", optional = true }
Then you can use cfg
and cfg_attr
to only enable the wasm_bindgen
attributes when the feature is enabled:
#[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
}
}
#[wasm_bindgen]
the structs, using Rust's conditional compilation alongside features to only#[wasm_bindgen]
when the crate that depends on lib requires it to – Larousse