WebAssembly导出的函数怎么在JS里调用不生效?
我用Rust编译了一个.wasm文件,导出了一个add函数,但在JS里调用时总是undefined,不知道是哪步出错了。已经确认wasm加载成功了,但instance.exports里看不到我的函数。
这是我在HTML里加载和调用的代码:
<script type="module">
const wasm = await WebAssembly.instantiateStreaming(fetch('pkg/my_wasm_bg.wasm'));
console.log(wasm.instance.exports); // 这里没看到add函数
// const result = wasm.instance.exports.add(1, 2); // 报错:add is not a function
</script>
问题原因:wasm-bindgen在编译时会生成两部分东西,一个是.wasm二进制文件,另一个是.js胶水代码。你只加载了.wasm,但那些导出函数实际上是通过JS胶水代码包装之后才能正常调用的。
正确的做法是这样的:
首先,确保你的Rust代码里函数标记了 #[wasm_bindgen],比如:
然后编译的时候用 wasm-pack build --target web
在HTML/JS里正确的调用方式应该是:
你之前那么写的问题是,wasm-bindgen导出的函数实际上是通过JS胶水代码里的WebAssembly.Instance在内部处理过的,不是直接放在instance.exports里的。你需要先跑一遍init(),它会帮你正确实例化wasm并把导出函数暴露出来。
如果你不想用wasm-bindgen,想直接裸写wasm导出,那也行,但就得用wasm-bindgen-cli或者直接用wat手写WebAssembly文本格式了,那样导出函数会直接出现在instance.exports里。不过既然你已经在用Rust了,用wasm-bindgen还是最省心的办法。