版本区别

截止到目前(2024-06-11)位置,rust 支持的 wasm target 如下:

$ rustup target list | grep wasm
wasm32-unknown-emscripten
wasm32-unknown-unknown
wasm32-wasi
wasm32-wasi-preview1-threads

上述三个版本区别如下:

版本解释

wasm32-unknown-emscripten

使用 emscripten 编译生成 wasm,适用于包含 C/C++ 的项目。

wasm32-unknown-unknown

借助 wasm workgroup 编写的标准库来生成面向 wasm 的代码。

wasm32-wasi

wasi 是 WebAssembly System Interface 的缩写。旨在通过规定系统接口允许 wasm 运行在超出浏览器的环境下。允许 wasm 运行在主机环境中。

Emscripten

rust binary target 使用 wasm32-unknown-emscripten 编译后会同时生成一个 js 文件和一个 wasm 文件。js 文件包含了一些胶水代码用来使用 wasm。下面的代码描述了如何将一个 rust 函数导出到 wasm 中:

#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn js_parse_loongdoc(source: *mut c_char) -> *const c_char {
    let source = unsafe { CStr::from_ptr(source) }
        .to_string_lossy()
        .to_string();

    let v = match parse_loongdoc(source.as_bytes()) {
        Ok(v) => serde_json::to_string(&v).unwrap(),
        Err(err) => {
            println!("parse failed: {err:?}");
            Default::default()
        }
    };

    let res = ManuallyDrop::new(CString::new(v).unwrap());
    res.as_ptr()
}

编译时需要添加参数将部分胶水函数导出:

$ EMCC_CFLAGS="-sEXPORTED_RUNTIME_METHODS=ccall,cwrap,cfree" cargo build -F wasm --target=wasm32-unknown-emscripten

然后在 nextjs 中使用:

<Script
  src="loongdoc.js"
  onLoad={() => {
    Module.onRuntimeInitialized = function () {
      var parser = Module.cwrap('js_parse_loongdoc', 'string', ['string'])
      console.log(parser("= title0"))
    }
  }}
></Script
  • 当 js 加载完成后会生成一个 Module 全局变量,此变量可以用来访问 wasm 中的信息。除此之外,还可以在 js 加载之前设置此环境变量以设置回调函数。

  • Emscripten 中可以导出的函数定义在 preamble.js 中。

  • Rust wasm 生态中大部分库都是以 wasm32-unknown-unknown 为 target 的。并不支持 wasm32-unknown-emscripten。比如 wasm-bindgen

Last moify: 2022-12-04 15:11:33
Build time:2025-07-18 09:41:42
Powered By asphinx