Передача строк между Rust и JavaScript при сборке с помощью 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. Я делаю содержимое каталога pkg доступным для проекта через файл manifest.json как 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 внизу.
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");
})();
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!
})();