Emscripten触发意外函数调用问题及正确实现方法咨询
解决Emscripten运行时初始化与函数调用问题
问题核心分析
你遇到的问题包含两个关键点:
- RuntimeError报错:调用
add函数时Emscripten的WebAssembly运行时还未完成初始化,无法执行导出的本地函数; cwrap参数错误:add接收两个整数参数,但你只声明了一个参数类型;- 关于
run()被意外调用的误解:并非页面加载时自动触发函数,而是未初始化运行时就调用函数导致的报错,让你误以为函数被提前执行。
修正步骤
1. 修复cwrap的参数定义
add函数需要两个number类型参数,因此cwrap的第三个参数数组必须包含两个元素:
var add = cwrap("add", "number", ["number", "number"]);
2. 等待Emscripten运行时初始化完成
Emscripten生成的JS模块默认异步初始化,必须等运行时准备就绪才能调用导出函数,以下两种方式任选其一:
方式一:使用onRuntimeInitialized回调
提前定义Module对象并设置初始化完成的回调,确保函数调用时机正确:
<!DOCTYPE html> <html> <head> <script> // 提前声明Module,指定初始化完成回调 var Module = { onRuntimeInitialized: function() { console.log("Emscripten运行时已准备就绪"); } }; </script> <script src="a.out.js"></script> <script> function run(){ alert("Run!"); // 调用cwrap绑定函数 var add = Module.cwrap("add", "number", ["number", "number"]); var result = add(12, 13); document.getElementById('output').value = result; } </script> </head> <body> <button onclick="run();">Run!</button> <input id="output"> </body> </html>
方式二:用async/await等待模块就绪
如果环境支持ES6异步语法,可使用更简洁的异步等待方式:
<!DOCTYPE html> <html> <head> <script src="a.out.js"></script> <script> // 页面加载时等待模块初始化 window.onload = async () => { await Module.ready; console.log("运行时初始化完成"); }; async function run(){ alert("Run!"); // 确保模块就绪后再调用函数 await Module.ready; var add = Module.cwrap("add", "number", ["number", "number"]); var result = add(12, 13); document.getElementById('output').value = result; } </script> </head> <body> <button onclick="run();">Run!</button> <input id="output"> </body> </html>
3. 可选:编译时添加运行时保留参数
为避免运行时自动退出,可在编译命令中添加-sNO_EXIT_RUNTIME=1,确保运行时持续可用:
em++ test.cpp -sEXPORTED_FUNCTIONS=_add -sEXPORTED_RUNTIME_METHODS=ccall,cwrap -sNO_EXIT_RUNTIME=1
验证效果
完成修改后点击按钮,会正常弹出提示、计算12+13的结果25并显示在输入框中,不再出现运行时未初始化的错误。
内容的提问来源于stack exchange,提问作者Bubaya
相关产品推荐
相关产品推荐

