在JavaScript中不使用wasm_bindgen从Rust WASM打印字符串

nhaq1z21  于 11个月前  发布在  Java
关注(0)|答案(1)|浏览(136)

问题

为了更好地理解WASM,我想尝试在不使用wasm_bindgen的情况下将一些字符串数据从Rust WASM模块传递到JavaScript。我试图调用一个Rust函数,该函数返回一个包含字符串指针及其长度的元组。模块正确导入,但当我调用该函数时,我在JS中获得undefined

调研

我提到了这个被广泛接受的答案,但它似乎已经过时了,而且可能有点不符合人体工程学。当然,更新后的答案使用了wasm_bindgen。(注意:我并不反对使用wasm_bindgen,我只是想更好地理解发生了什么。)

代码

我的 rust :

use std::ptr;

#[no_mangle]
pub fn greet(name: &str) -> (u8, usize) {
    let s = format!("Hello, {}!", name).to_string();
    let len = s.len();
    let ptr = ptr::addr_of!(s);
    (ptr as u8, len)
}

字符串
JS缩写:

let wasm = wasmModule.instance.exports;

//After WASM load:
console.log( wasm?.greet("WebAssembly") );

期望和假设

  • Rust的新手,WASM的新手。
  • 我的期望是从wasm.greet得到一个ArrayBuffer,然后我需要将其分解并用于引用wasm.memory中的字节,但我从未得到过ArrayBuffer。
  • 我希望返回那些整数值(指针和长度)(因为它们在函数响应中被复制),但我假设我的下一个问题是,当我在JS中引用它时,字符串本身不再存在于WASM内存中。我将在稍后处理这个问题,除非有人提供一些关于如何处理它的建议。
  • 有没有可能函数返回undefined,因为当函数返回时,我发送的整数在内存中不存在?
unftdfkk

unftdfkk1#

基于this answer,并通过修改自己的代码确认,问题是返回一个元组。你应该暂时只返回一个值(显然不是所有的环境都支持返回多个值)。
所以,我在这个SO答案中提到的“不符合人体工程学”的代码实际上在某种程度上是必要的,因为你不能同时返回指针和长度。
JS代码获取从指针和长度的单独函数调用返回的字符串:

function wasmString(loc, len) {
    const mem = new Uint8Array(wasm?.memory?.buffer, loc, len);
    console.log(mem);
    const dec = new TextDecoder();
    return dec.decode(mem);
}

字符串
其他一些可能有帮助的注解:

  • 从WASM返回指针和长度的工作原理令人怀疑,没有错误!字符串的生存期要么不是一个问题,要么是一个问题,当该地址的数据被覆盖时,它会慢慢出现。我不认为我信任它。
  • 打印的字符串是“Hello,!",这意味着JS的字符串参数不会传递给Rust。这可能是wasm_bindgen的魔力。调查。

相关问题