Rust 编译为WebAssembly 在前端项目中使用( 四 )

  • "hello_world.d.ts"
  • "package.json"
  • 这些文件也可以通过使用以下wasm-bindgen命令手动生成:
    wasm-bindgen target/wasm32-unknown-unknown/debug/hello_world.wasm --out-dir ./pkg浏览器调用顺序以下显示了当我们在浏览器中访问localhost:8080时发生的函数调用序列 。
    1. index.js
    2. hello_world.js (调用hello_world_bg.js)
    3. helloworld_bg.wasm
    index.jsconst rust = import('./pkg/hello_world.js');rust.then(m => m.helloworld('World!')).catch(console.error);index.js 导入了 hello_world.js 并调用其中的 helloworld 函数 。
    hello_world.js下面是hello_world.js的内容,在其中它调用了helloworld_bg.wasm
    import * as wasm from "./hello_world_bg.wasm";import { __wbg_set_wasm } from "./hello_world_bg.js";__wbg_set_wasm(wasm);export * from "./hello_world_bg.js";hello_world_bg.js// ...省去了部分代码export function helloworld(name) {const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);const len0 = WASM_VECTOR_LEN;wasm.helloworld(ptr0, len0);}hello_world_bg.js 文件是由wasm-bindgen自动生成的,它包含了用于将DOM和JavaScript函数导入到Rust中的JavaScript粘合代码 。它还在生成的WebAssembly函数上向JavaScript公开了API 。
    Rust WebAssembly专注于将WebAssembly与现有的JavaScript应用程序集成在一起 。为了实现这一目标,我们需要在JavaScript和WebAssembly函数之间「传递不同的值、对象或结构 。这并不容易,因为需要协调两个不同系统的不同对象类型」 。
    更糟糕的是,当前WebAssembly仅支持「整数」和「浮点数」,不支持字符串 。这意味着我们不能简单地将字符串传递给WebAssembly函数 。
    要将字符串传递给WebAssembly,我们需要「将字符串转换为数字」(请注意在webpack.config.js中指定的TextEncoderAPI),将这些数字放入WebAssembly的内存空间中,最后「返回一个指向字符串的指针」给WebAssembly函数,以便在JavaScript中使用它 。在最后 , 我们需要释放WebAssembly使用的字符串内存空间 。
    如果我们查看上面的JavaScript代码,这正是自动执行的操作 。helloworld函数首先调用passStringToWasm 。
    • 这个函数在WebAssembly中「创建一些内存空间」,将我们的字符串转换为数字,将数字写入内存空间,并返回一个指向字符串的指针 。

    Rust 编译为WebAssembly 在前端项目中使用

    文章插图
    图片
    • 然后将指针传递给wasm.helloworld来执行JavaScript的alert 。最后,wasm.__wbindgen_free释放了内存 。
    如果只是传递一个简单的字符串 , 我们可能可以自己处理,但考虑到当涉及到更复杂的对象和结构时,这个工作会很快变得非常复杂 。这说明了wasm-bindgen在Rust WebAssembly开发中的重要性 。
    反编译wasm到txt在前面的步骤中,我们注意到wasm-bindgen生成了一个hello_world.js文件 , 其中的函数调用到我们生成的hello_world_bg.wasm中的WebAssembly代码 。
    基本上 , hello_world.js充当其他JavaScript(如index.js)与生成的WebAssembly的helloworld_bg.wasm之间的桥梁 。
    我们可以通过输入以下命令进一步探索helloworld_bg.wasm:
    wasm2wat hello_world_bg.wasm > hello_world.txt这个命令使用wabt将WebAssembly转换为WebAssembly文本格式,并将其保存到一个hello_world.txt文件中 。打开helloworld.txt文件,然后查找$helloworld函数 。这是我们在src/lib.rs中定义的helloworld函数的生成WebAssembly函数 。
    $helloworld函数
    Rust 编译为WebAssembly 在前端项目中使用

    文章插图
    图片
    在helloworld.txt中查找以下行:
    (export "helloworld" (func $helloworld))这一行导出了wasm.helloworld供宿主调用的WebAssembly函数 。我们通过hello_world_bg.js中的wasm.helloworld来调用这个WebAssembly函数 。
    Rust 编译为WebAssembly 在前端项目中使用

    文章插图
    图片
    接下来 , 查找以下行:
    (import "./hello_world_bg.js" "__wbg_alert_9ea5a791b0d4c7a3" (func $hello_world::alert::__wbg_alert_9ea5a791b0d4c7a3::h93c656ecd0e94e40 (type 4)))这对应于在hello_world_bg.js中生成的以下JavaScript函数:


    推荐阅读