使用 wasm-pack 构建时在 Rust 和 JavaScript 之间传递字符串
Passing strings between Rust and JavaScript when building with wasm-pack
我正在构建一个 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 错误输出。
问题在于您如何加载代码:
(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
从 .default(...)
返回的是一个具有原始 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!
})();
我正在构建一个 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 错误输出。
问题在于您如何加载代码:
(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
从 .default(...)
返回的是一个具有原始 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!
})();