#[wasm_bindgen] public 结构和函数是否可以在另一个 crate 中定义?

Is it possible to #[wasm_bindgen] public structs and functions defined in another crate?

我有一个板条箱 lib,其中包含大量结构和 impl。然后我有另一个名为 web 的,它将使核心 lib 可移植到 Web。还有 api 以防我希望该应用程序是服务器端的。

我不想要的是仅在 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" featurewasm-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
    }
}