【问题标题】:Passing strings between Rust and JavaScript when building with wasm-pack使用 wasm-pack 构建时在 Rust 和 JavaScript 之间传递字符串
【发布时间】:2020-06-15 04:09:31
【问题描述】:

我正在构建一个 Chrome 扩展程序,并选择使用一些 WebAssembly 功能。我使用 wasm-pack 来构建源代码,因为它提供了一个--target web,可以降低插入 Wasm 函数的复杂性。在 Rust 和 JS 之间传递整数值可以无缝地工作,但我似乎无法将字符串传递给 Rust,反之亦然。

这是我正在使用的:

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);

    #[wasm_bindgen(js_namespace = console)]
    fn log(x: &str);
} 

#[wasm_bindgen]
pub extern "C" fn add_two(x: i32) -> i32 {
   x + 2
}

#[wasm_bindgen]
pub fn hello(name: &str) {
    log("Hello") // <-- passing a '&str' directly works. I can see it in the browser.
    log(name) // <-- does not seem to work. There is no output
    alert(&format!("Hello {}", name)); // <- Only output im getting is "Hello !"
}

更新:关于我如何导入和实例化 wasm 的更多信息

使用 wasm-pack 构建并将生成的 pkg 目录导入我的 JS 文件夹后。我通过 manifest.json 文件将 pkg 目录的内容作为 web_resource 提供给项目。

这是我在 content_script.js 中加载脚本的方式

(async function() {
  // Get the JS File
  const src = await import("/pkg/rusty.js");
  // Fetch the wasm file.
  const wasm_src = chrome.extension.getURL("/pkg/rusty_bg.wasm");
  //src has an exported function 'default' that initializes the WebAssembly module.
  let wasm = await src.default(wasm_src);

  wasm.hello("stack-overflow");
})();

我还注意到我生成的 wasm_bg 文件在底部有一些 Rust 错误输出。

【问题讨论】:

  • How to return a string (or similar) from Rust in WebAssembly?的答案可能会回答您的问题。如果没有,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。
  • 发布的问题没有使用 wasm-bindgen,这点差别很小。这意味着我应该能够传递一个字符串,因为它代表我完成了所有繁重的工作。
  • 您展示的所有选项都应该有效;似乎是问题并且未在上面的代码中显示的是您如何获取您正在调用函数的wasm 对象。确保您正在导入生成的主要 JavaScript 模块,而不仅仅是直接导入 WebAssembly 文件。
  • @RReverser 。我在 chrome 扩展程序中运行它。这意味着我必须使用 wasm-pack 来获得可以轻松导入到我的扩展文件中的可用 JS 输出。 wasm-pack build --target web -- --features wee_alloc. 输出带有 JS 的 pkg 目录,可以在 chrome 中加载而不会出现任何导入错误
  • @mar-tina 这仍然没有显示您如何获得wasm 对象。您能否更新代码 sn-p 以显示您如何导入生成的包?

标签: rust webassembly rust-cargo wasm-bindgen wasm-pack


【解决方案1】:

问题在于您如何加载代码:

(async function() {
  // Get the JS File
  const src = await import("/pkg/rusty.js");
  // Fetch the wasm file.
  const wasm_src = chrome.extension.getURL("/pkg/rusty_bg.wasm");
  //src has an exported function 'default' that initializes the WebAssembly module.
  let wasm = await src.default(wasm_src);

  wasm.hello("stack-overflow");
})();

.default(...) 返回的wasm 是一个具有原始 WebAssembly 导出的对象,只能对原始数字进行操作。

在这种情况下,wasm.hello 需要两个整数——WebAssembly 内存中字符串的指针和长度——并且 JavaScript 愉快地将 "stack-overflow" 转换为 0 并提供另一个 0 作为默认值,这就是为什么你在 Rust 端得到一个空字符串的原因。

您想要的是负责正确转换的函数的包装版本。这些直接存在于 .js 文件的导入中:

(async function() {
  // Get the JS File
  const rusty = await import("/pkg/rusty.js");
  // Fetch the wasm file.
  const wasm_src = chrome.extension.getURL("/pkg/rusty_bg.wasm");
  // rusty has an exported function 'default' that initializes the WebAssembly module.
  await rusty.default(wasm_src);

  rusty.hello("stack-overflow"); // it works!
})();

【讨论】:

  • 成功了!非常感谢。我花了一天时间才找到这个。
猜你喜欢
  • 2020-09-11
  • 2021-09-15
  • 2019-09-11
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多