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

如何用Emscripten和WebAssembly在C++中返回结构体向量至JS

解决方法

问题根源在于int64_t类型的字段绑定处理:JavaScript的Number类型无法精确表示所有64位整数,Emscripten默认的类型转换逻辑会触发异常。只需修改C++绑定代码,显式指定将int64_t转换为JavaScript的BigInt类型即可解决。

修改后的C++代码

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

using Player = int;
using Action = int64_t;

struct PlayerAction {
    Player player;
    Action action;

    bool operator==(const PlayerAction& other) const {
        return player == other.player && action == other.action;
    }
};

std::vector<PlayerAction> getAction() {
    std::vector<PlayerAction> action;
    
    PlayerAction action1 = {0, 2};
    PlayerAction action2 = {1, 4};
    
    action.push_back(action1);
    action.push_back(action2);
    
    return action;
}

// Bindings
EMSCRIPTEN_BINDINGS(my_module) {
    emscripten::value_object<PlayerAction>("PlayerAction")
        .field("player", &PlayerAction::player)
        // 显式指定将int64_t转换为JavaScript BigInt
        .field<emscripten::bigint>("action", &PlayerAction::action);

    emscripten::function("getAction", &getAction);
    emscripten::register_vector<PlayerAction>("vector<PlayerAction>");
}

编译注意事项

编译时必须添加--bind参数,否则Emscripten的C++/JS绑定逻辑不会生效:

emcc 你的源文件名.cpp -o exemplo.js --bind

JavaScript端使用示例

修改后调用getAction()会返回包含目标对象的数组,action字段会以BigInt类型呈现,可正常访问或转换:

var Module = {
    onRuntimeInitialized: function() {
        const actions = Module.getAction();
        actions.forEach(item => {
            console.log(`玩家ID:${item.player},动作值:${item.action}`);
            // 若确认动作值在32位整数范围内,可转为普通数字
            // console.log(`动作值(数字类型):${Number(item.action)}`);
        });
    }
}

核心说明

  • emscripten::bigint转换器会将C++的64位整数类型映射为JavaScript的BigInt,彻底避免精度丢失问题。
  • --bind参数是启用Emscripten绑定机制的必要条件,缺失会导致绑定函数无法被JS识别。

内容的提问来源于stack exchange,提问作者Lucas celestino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:05:10