如何用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
相关产品推荐
相关产品推荐

