当前位置: 首页 > news >正文

从原始 Import/Export 到 wasm-bindgen 与自定义 Section

1. 基础能力:在 wasm 层导入 / 导出函数

1.1 Rust 侧 —— extern & #[no_mangle]

// ① 从 JS 模块 "mod" 导入 foo()
#[link(wasm_import_module = "mod")]
extern "C" {fn foo();          // 只能使用数字类型参数 / 返回值
}// ② 导出 bar() 给 JS 调用
#[no_mangle]
pub extern "C" fn bar() {// ...
}
  • #[link(wasm_import_module)]:指定 module name,不写默认为 "env"
  • #[no_mangle]:保持符号名 bar 不被 Rust 重整(mangling),从而在 wasm 导出表中可见。
  • wasm 目前仅支持 i32 / i64 / f32 / f64 原始数值类型,无指针 / 结构体。

1.2 JS 侧 —— ES6 WebAssembly.instantiate

import wasmUrl from "./pkg/app_bg.wasm?url";const memory = new WebAssembly.Memory({ initial: 1 });
const imports = {mod: { foo: () => console.log("JS foo() 被调用") },env: { memory },                 // 默认导入 memory,也可使用 wasm 自带
};const { instance } = await WebAssembly.instantiateStreaming(fetch(wasmUrl),imports,
);// 调用 Rust 导出的 bar()
instance.exports.bar();
  • module name + import name 必须与 Rust 侧匹配。
  • 实例化后,通过 instance.exports.<fn> 调用 Rust 函数。

2. 超越纯数字:共享内存 & wasm-bindgen

2.1 线性内存模型

  • wasm 拥有独立的连续字节数组(ArrayBuffer),JS 可读写

  • wasm 代码 无法直接触碰 任何 JS 对象或 DOM;只能看见数字、读写 memory。

  • 因此高级数据传递需 两步

    1. Copy:JS 把字节写入 wasm memory,再传入指针+长度。
    2. Handle:创建一个 JS “堆”数组,存放对象引用,在 wasm 里用整数 ID 代表对象。

2.2 wasm-bindgen:胶水自动生成

use wasm_bindgen::prelude::*;// 导出给 JS
#[wasm_bindgen]
pub fn greet(name: &str) {alert(&format!("Hello, {name}!"));
}// 从 JS 导入
#[wasm_bindgen]
extern "C" {#[wasm_bindgen(js_namespace = console)]fn log(s: &str);
}
  • wasm-bindgen 会生成 JS glue code,自动完成字符串复制、对象句柄管理;
  • JS 侧直接 import init from './pkg/app.js',无需手写内存拷贝逻辑。

3. Custom Section:在 wasm 中嵌入自定义数据

3.1 Rust 写入自定义段

#[link_section = "hello"]
pub static HELLO_SECTION: [u8; 24] = *b"This is a custom section";
  • link_section 将静态数组放入 wasm 文件名为 hello 的自定义段中。
  • 内容为任意二进制数据,编译后 只读

3.2 JS 读取自定义段

const mod = await WebAssembly.compileStreaming(fetch("sections.wasm"));
const buffers = WebAssembly.Module.customSections(mod, "hello");const text = new TextDecoder().decode(buffers[0]);
console.log(text); // "This is a custom section"
  • customSections(module, name) 返回 ArrayBuffer[],可能存在多段同名 section。
  • 常见用途:版本号、元数据、校验和等随模块分发。

4. 典型数据交互套路

需求方案
传递大字符串 / Uint8ArrayJS TextEncoder → 写入 memory → Rust slice::from_raw_parts
wasm 调 JS DOMwasm 储存 elementId 整数 → JS imports 提供操作函数
回调 / 事件在 JS 堆里存闭包,返回句柄;wasm 保存句柄并回调时再由 JS 执行

实际项目中,优先使用 wasm-bindgen / js-sys / web-sys 自动生成绑定,极大简化指针与堆句柄管理。

5. 小结

  • 裸 import/export 仅适合数值级互调;字符串与复杂对象需自行处理内存。
  • wasm-bindgen = 自动绑 glue + 把 Rust String/Vec<u8> ↔ JS 对象互转。
  • Custom Section 让你在模块中注入任意元数据,JS 端可在实例化前读取。
  • 熟练掌握三板斧:extern/Memory、bindgen、customSections,即可完成从低级数值 API 到高级对象交互的全链路开发。祝你玩转 Rust + WebAssembly!
http://www.dtcms.com/a/313926.html

相关文章:

  • Ethereum:拥抱开源,OpenZeppelin 未来的两大基石 Relayers 与 Monitor
  • 嵌入式硬件中三极管推挽电路控制与实现
  • 模型蒸馏(Distillation):原理、算法、应用
  • 突破Transformer局限!MICN:线性复杂度实现时序预测新高度
  • LeetCode 132:分割回文串 II
  • 作物生长模型Oryza V3实战19:场景模拟常见问题及解决
  • Redis7基数统计(HyperLogLog)深度分析
  • PostGIS面试题及详细答案120道之 (091-100 )
  • 读懂Node Exporter采集数据的原理
  • Spring Boot + ShardingSphere 实现分库分表 + 读写分离实战
  • day15 SPI
  • PE 方法中的海面边界建模:光滑与粗糙海面条件解析
  • Android JUnit 测试框架详解:从基础到高级实践
  • C 语言枚举、typedef 与预处理详解
  • TinUI较复杂面板布局演示
  • 使用1panel将http升级至https的过程
  • 8.高斯混合模型
  • Next Terminal 实战:内网无密码安全登录
  • Ubuntu共享文件夹权限设置
  • 面试题:闭包和循环的异步如何结合
  • 《算法导论》第 1 章 - 算法在计算中的作用
  • 微型化 IMU:重塑无人机与机器人的性能边界
  • 从HTTP到WebSocket:打造极速实时通讯体验
  • 微帧GPU视频硬编优化引擎:面向人工智能大时代的AI算法与硬编协同优化方案
  • web第一次作业
  • cf Educational Codeforces Round 177 C. Disappearing Permutation
  • C++八股文——设计模式
  • 分布式版本控制工具Git
  • 微服务配置管理:Spring Cloud Alibaba Nacos 实践
  • Scrapy爬虫集成MongoDB存储