You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust + WASM中返回二维向量的函数签名适配问题

解决wasm_bindgen嵌套Vec类型不兼容问题

wasm_bindgen 默认仅支持与JS原生类型直接映射的Rust类型(比如Vec<isize>可转为JS数组),但嵌套容器类型(如Vec<Vec<isize>>、Vec<Vec<(usize, usize)>>)没有默认的跨语言转换实现,因此会触发trait bound JsObject不满足的错误。以下是两种可行的解决方案:

方案一:使用JsValue手动序列化/反序列化

通过serde_json在Rust类型与JS值之间手动转换,适用于复杂嵌套结构:

  1. 添加依赖到Cargo.toml:
[dependencies]
wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
  1. 修改函数实现:
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};

// 定义输入结构,用于解析JS传入的数据
#[derive(Debug, Deserialize)]
struct FindInput {
    matrix: Vec<Vec<isize>>,
    threshold: usize,
}

// 定义输出结构,用于序列化为JS值
#[derive(Debug, Serialize)]
struct FindOutput {
    result: Vec<Vec<(usize, usize)>>,
}

#[wasm_bindgen]
pub fn find(input: JsValue) -> Result<JsValue, JsValue> {
    // 解析JS输入到Rust结构
    let input = serde_json::from_value(input)
        .map_err(|e| JsValue::from_str(&format!("输入解析失败: {}", e)))?;

    // 原业务逻辑示例
    let mut result = Vec::new();
    for (row_idx, row) in input.matrix.iter().enumerate() {
        let mut coords = Vec::new();
        for (col_idx, &val) in row.iter().enumerate() {
            if val as usize <= input.threshold {
                coords.push((row_idx, col_idx));
            }
        }
        result.push(coords);
    }

    // 序列化结果为JS值返回
    let output = FindOutput { result };
    serde_json::to_value(output)
        .map_err(|e| JsValue::from_str(&format!("输出序列化失败: {}", e)))
}
  1. JS端调用示例:
import { find } from './your_wasm_module';

const input = {
    matrix: [[1, 5, 3], [2, 4, 6]],
    threshold: 3
};
const result = await find(input);
// result.result 为 [[[0,0], [0,2]], [[1,0]]]

方案二:启用wasm_bindgen的serde集成(更简洁)

通过启用wasm_bindgen的serde特性,让支持Serialize/Deserialize的Rust类型自动与JS类型互转:

  1. 修改Cargo.toml依赖:
[dependencies]
wasm-bindgen = { version = "0.2", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
  1. 调整函数签名与实现:
    注意:直接使用元组(usize, usize)可能存在序列化兼容性问题,建议包装为结构体或数组:
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};

// 包装坐标类型,实现序列化/反序列化
#[derive(Debug, Serialize, Deserialize)]
struct Coord(usize, usize);

#[wasm_bindgen]
pub fn find(matrix: Vec<Vec<isize>>, threshold: usize) -> Vec<Vec<Coord>> {
    let mut result = Vec::new();
    for (row_idx, row) in matrix.iter().enumerate() {
        let mut coords = Vec::new();
        for (col_idx, &val) in row.iter().enumerate() {
            if val as usize <= threshold {
                coords.push(Coord(row_idx, col_idx));
            }
        }
        result.push(coords);
    }
    result
}
  1. JS端调用示例:
import { find } from './your_wasm_module';

const matrix = [[1, 5, 3], [2, 4, 6]];
const threshold = 3;
const result = find(matrix, threshold);
// result 为 [[[0,0], [0,2]], [[1,0]]]

内容的提问来源于stack exchange,提问作者Roman Mahotskyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:36:28