WebAssembly导出的函数怎么传字符串给JS?

Prog.喜静 阅读 7

我用Rust编译了一个.wasm模块,里面有个函数想返回一个字符串给JavaScript,但发现直接return字符串会报错。查了文档说要通过内存传递,但具体怎么操作完全懵了。

我试过在Rust里用std::ffi::CString,然后导出指针,但在JS里用UTF8ToString()读取时总是乱码或者崩溃。是不是哪里没对齐?下面是我的Rust和JS代码:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn get_message() -> *const u8 {
    let msg = b"Hello from WASM!";
    msg.as_ptr()
}

JS这边是这么调的:

import { get_message } from './pkg/my_wasm.js';

const ptr = get_message();
const str = UTF8ToString(ptr);
console.log(str); // 输出乱码或者直接报错
我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
Mc.溪纯
Mc.溪纯 Lv1
兄弟,你这又是何苦。既然都用上了 wasm-bindgen,那就别自己手动去摆弄指针了,这玩意儿坑多水深,容易掉进内存管理的陷阱里。你现在的代码里,b"..." 只是个静态字面量切片,没有在堆上分配,而且后面也没加 结束符,JS 里的 UTF8ToString 根本不知道读到哪才算完,不崩溃才怪。

最简单的办法就是直接用 Rust 的 String 类型,wasm-bindgen 会自动帮你搞定内存分配、拷贝以及 JS 这边的接收,你完全不用操心。

Rust 代码改成这样就行:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn get_message() -> String {
let msg = String::from("Hello from WASM!");
msg
}


JS 那边更简单,直接拿就是了:

import { get_message } from './pkg/my_wasm.js';

const str = get_message();
console.log(str); // 直接就是字符串,不用转码


如果你非要用指针传(比如为了极致性能不想拷贝),那得在 Rust 里把字符串塞到 WASM 的线性内存里,也就是堆上,并且得手动管理释放,不然铁定内存泄漏。但在 wasm-bindgen 的生态下,直接传 String 或者 &str 才是正解,别跟自己过不去。
点赞 1
2026-03-04 17:13