Node.js调用C++编译WebAssembly报instance.sum is not a function问题问询
问题解决方案
1. 修复sum is not a function报错
Emscripten默认会给C/C++导出的函数名前加下划线前缀,且如果没有显式指定导出规则,编译器可能会把未被引用的函数树摇删除,对应修复方式如下:
- 调整编译命令,显式指定要导出的函数:
em++ cpp-sources/Sum/sum.cpp -o sum/sum.js -s MODULARIZE -s EXPORTED_FUNCTIONS=['_sum'] -s EXPORTED_RUNTIME_METHODS=['ccall','cwrap']
- 调用时匹配函数命名规则即可:
public getSum(){ const factory = require(__dirname + "/sum/sum.js"); factory().then((instance) => { // 方式1:直接调用带前缀的导出函数 console.log(instance._sum(5, 6)); // 方式2:使用emscripten封装的ccall方法调用 console.log(instance.ccall('sum', 'number', ['number', 'number'], [5, 6])); }); }
如果不需要自动生成的JS胶水代码,要直接实例化wasm文件,使用如下编译命令生成无依赖的纯wasm文件即可:
em++ cpp-sources/Sum/sum.cpp -o sum/sum.wasm --no-entry -s STANDALONE_WASM=1 -s EXPORTED_FUNCTIONS=['_sum'] -O2
生成的文件直接用原生WebAssembly.instantiate实例化,调用exports._sum即可正常执行。
2. 修复wasi_snapshot_preview1报错
你之前使用的-s LINKABLE=1参数会默认启用WASI接口依赖,Node.js原生没有内置WASI实现,才会抛出该错误:
- 不需要WASI能力的场景直接添加编译参数
-s STANDALONE_WASM=1即可关闭WASI依赖,不需要额外修改JS调用代码 - 确实需要用到WASI能力的场景,安装
@wasmer/wasi等WASI实现包,在实例化wasm时传入对应WASI接口配置即可。
3. 修复无法引入<emscripten.h>的问题
emsdk_env.bat只会对当前运行的命令行窗口生效,如果你执行完后切换了VSCode终端、新的CMD窗口,环境变量会失效导致编译器找不到头文件路径:
- 临时方案:每次编译前先在当前终端进入emsdk目录,依次执行
emsdk activate latest、emsdk_env.bat,确认环境变量生效后再执行em++编译命令 - 永久方案:手动将emsdk根目录、emsdk/upstream/emscripten、emsdk/node/[对应node版本号]/bin三个路径添加到Windows系统环境变量中,重启终端后即可永久生效。
内容的提问来源于stack exchange,提问作者Matej Peluha
相关产品推荐
相关产品推荐

