我已经用Emscripten编译了一个C函数,并编写了此JS包装器,该包装器在交互式Node.js shell中可以正常工作:
// script generated by Emscripten
const _smaz = require("./_smaz");
// exported wrapper function
exports.compress = function(str_in) {
var encoded = encoder.encode(str_in);
var out_heap = _smaz['_malloc'](encoded.length * 8);
...
}
但是,在我的应用程序中立即调用该函数时,_malloc
失败:
TypeError: Cannot read property 'apply' of undefined
at Object.a._malloc
即使添加100ms setTimeout
也可以解决问题。看起来像编译的Emscripten东西是异步加载的,功能不能立即使用。
处理此问题的正确方法是什么? Emscripten docs建议在加载“页面”后添加Module['onRuntimeInitialized']
函数,但是我不确定在服务器端Node.js应用中应该将其放置在什么位置,或者不确定它是否完全适用。
这是我的编译方式:
emcc smaz.c -O2 -o _smaz.js --closure 1 -s EXPORTED_FUNCTIONS="['_smaz_compress', '_smaz_decompress']" -s 'EXTRA_EXPORTED_RUNTIME_METHODS=["ccall", "cwrap"]'
结果是有两个emcc
编译器选项可禁用异步启动/加载行为:-s BINARYEN_ASYNC_COMPILATION=0
和-s SINGLE_FILE=1
。这为我解决了问题。
从相关的GitHub issue:
一般来说,emscripten尝试为wasm异步启动,因为这是浏览器可以最优化的地方,更糟糕的是,Chrome当前对同步编译的大小有限制(希望很快会修复)。但是您可以强制进行同步编译用
-s BINARYEN_ASYNC_COMPILATION=0
。这仍然需要获取wasm二进制文件。默认情况下,我们获取它是异步的,但是如果您有办法自己获得它,您可以在
Module['wasmBinary']
上进行设置,我们将仅使用它同步地。或者,#5296将添加一个嵌入选项文件,使其同步可用。