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

如何通过WASM和Emscripten从JS向C++传递vector<class>?

解决Emscripten中JavaScript向C++传递vector<A>的问题

关键原理

Emscripten不会自动将JS数组隐式转换为C的std::vector<A>,必须通过Emscripten绑定生成的vector包装类来创建和填充实例,或者在C端添加适配JS数组的辅助函数。

步骤1:确认C++绑定代码的正确性

确保你已经正确注册了vector<A>的包装类,Emscripten的register_vector模板需要传入元素类型(而非别名):

#include <emscripten/bind.h>
#include <vector>

class A {
public:
    int x;
    A(int x_) : x(x_) {}
};

using AVector = std::vector<A>;

namespace util {
class Print {
public:
    static void print(const AVector& vec) {
        for (const auto& a : vec) {
            printf("A.x = %d\n", a.x);
        }
    }
};
}

EMSCRIPTEN_BINDINGS(my_module) {
    // 注册A类
    emscripten::class_<A>("A")
        .constructor<int>()
        .property("x", &A::x);
    
    // 注册vector<A>为AVector(关键:模板参数是元素类型A)
    emscripten::register_vector<A>("AVector");
    
    // 注册Print类的静态方法
    emscripten::class_<util::Print>("Print")
        .class_function("print", &util::Print::print);
}

步骤2:JavaScript端的正确实现

方式1:通过AVector包装类创建并填充

直接使用Emscripten生成的AVector构造函数和push_back方法来构建实例:

// 假设Module是Emscripten加载完成后的模块对象
function passVectorToCpp() {
    // 创建空的AVector实例
    const cppVector = new Module.AVector();
    
    // 向vector中添加A类实例
    cppVector.push_back(new Module.A(10));
    cppVector.push_back(new Module.A(20));
    cppVector.push_back(new Module.A(30));
    
    // 调用C++的Print.print方法
    Module.Print.print(cppVector);
}

// 等待WASM模块初始化完成后执行
Module.onRuntimeInitialized = passVectorToCpp;

方式2:将JS数组转换为AVector

如果已有JS数组,遍历数组逐个创建A实例并添加到AVector中:

function convertJsArrayToCppVector(jsArray) {
    const cppVector = new Module.AVector();
    jsArray.forEach(item => {
        // 从JS对象的x属性创建A实例
        const aInstance = new Module.A(item.x);
        cppVector.push_back(aInstance);
    });
    return cppVector;
}

// 使用示例
const jsData = [{x: 5}, {x: 15}, {x: 25}];
const convertedVec = convertJsArrayToCppVector(jsData);
Module.Print.print(convertedVec);

方式3:C++端添加适配函数(支持直接传JS数组)

如果想简化JS端代码,可以在C++中新增一个接受emscripten::val的重载方法,自动处理JS数组到vector<A>的转换:

// 在util::Print类中添加重载
static void print(const emscripten::val& jsArray) {
    AVector vec;
    const size_t len = jsArray["length"].as<size_t>();
    for (size_t i = 0; i < len; ++i) {
        emscripten::val aVal = jsArray[i];
        int x = aVal["x"].as<int>();
        vec.emplace_back(x);
    }
    print(vec); // 调用原有的print方法
}

此时JS端可以直接传递普通数组:

Module.Print.print([{x: 1}, {x: 2}, {x: 3}]);

常见错误原因

  • new AVector()无构造签名:未在C++绑定中调用register_vector<A>("AVector"),导致Emscripten未生成对应的JS包装类构造函数。
  • 普通JS数组无法传入:JS数组与C++std::vector内存结构完全不同,Emscripten不支持隐式转换,必须通过包装类或适配函数处理。

内容的提问来源于stack exchange,提问作者ayush bansal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:58:07