如何使用 wasm-bindgen 和 --target no-modules 导入 JavaScript 函数?

问题描述 投票:0回答:1

我正在尝试弄清楚如何使用 Rust 和 wasm-bindgen 调用 JavaScript 函数。由于缺乏浏览器支持,我无法将 wasm-bindgen 与 ES6 模块与 Web Worker 一起使用。

据我所知,声明存在一个 JavaScript 函数供我在 Rust 端调用是很简单的

#[wasm_bindgen]
extern {
    fn logProgress(percent: f64);
}

但是我不知道在哪里定义 JavaScript 实现。如果我尝试从 JavaScript 调用 Rust 函数来调用未定义的

logProgress
,那么我会收到运行时错误:
Error: logProgress is not defined

我可以从 wasm-bindgen 文档中看到,如果我将 wasm-bindgen 与 ES6 模块一起使用,那么我可以将 rust 代码更改为

#[wasm_bindgen(module = "/progress.js")]
extern {
    fn logProgress(percent: f64);
}

并在

progress.js

中声明 JavaScript 函数
export function logProgress(percent) {
    console.log(percent)
    // actual implementation would not just log
}

由于我是通过

wasm_bindgen
全局导入 Rust API,我想我应该能够在 Web Worker 中的同一部分周围定义实现,但我搜索了很多文档,但找不到关于如何做到这一点的任何信息。

importScripts('foo_wasm.js')
wasm_bindgen('foo_wasm_bg.wasm').then(fooWasmModule => {
    memory = fooWasmModule.memory
    const { Foo, Bar, Baz, foobar } = wasm_bindgen;
    // JS has 'imported' the Rust structs and functions
    // How to 'export' the JS functions to Rust?
}
javascript rust webassembly wasm-bindgen
1个回答
0
投票

以@eggyal 评论为指导。

wasm-bindgen
WorkerGlobalScope
板条箱内提供了
web-sys
类型,但是,您不能使用它,因为它不具有您在自己的worker中定义的功能。

所以你想要做的就是依靠ducktyping。您定义自己的

WorkerGlobalScope
类型,然后将导入视为对象的方法。

#[wasm_bindgen]
extern "C" {
  type WorkerGlobalScope;

  #[wasm_bindgen(method)]
  fn logProgress(this: &WorkerGlobalScope, percent: f64);
}

然后你可以像这样使用它:

#[wasm_bindgen]
pub fn call_from_worker() {
  let global = js_sys::global().dyn_into::<WorkerGlobalScope>();
  if let Ok(worker) = global {
    worker.logProgress(99.9);
  }
}

缺点是,如果您尝试在工作人员之外使用它,转换将会失败。

© www.soinside.com 2019 - 2024. All rights reserved.