emscripten:在 Node.js 中异步调用时,C 函数不是 "ready"
emscripten: C functions not "ready" when called asynchronously in Node.js
我用 Emscripten 编译了一个 C 库,并编写了可以在交互式 Node.js shell:
中正确交互的 JS
// script compiled by Emscripten
const _smaz = require("./_smaz");
var out_heap = _smaz['_malloc'](encoded.length * 8);
...
但是,当在我的应用程序中立即调用该函数时,_malloc
失败:
TypeError: Cannot read property 'apply' of undefined
at Object.a._malloc
即使添加 100 毫秒 setTimeout
也可以解决问题。看起来编译后的 Emscripten 东西是异步加载的,函数不能立即使用。
正确的处理方法是什么? Emscripten docs 建议在我的 "page" 加载后添加一个 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
编译器选项可以禁用异步 startup/loading 行为:-s BINARYEN_ASYNC_COMPILATION=0
和 -s SINGLE_FILE=1
。这解决了我的问题。
来自相关GitHub issue:
In general emscripten tries to do startup asynchronously for wasm,
because it's what browsers can best optimize, and worse, Chrome
currently has a limitation on the size of synchronous compilations
(hopefully will be fixed soon). But you can force sync compilation
with -s BINARYEN_ASYNC_COMPILATION=0
.
That still leaves fetching the wasm binary file. By default we fetch
it asynchronously, but if you have a way to get it yourself before,
you can set it on Module['wasmBinary']
and we will just use that
synchronously. Alternatively, #5296 will add an option to embed that
file, making it available synchronously.
我用 Emscripten 编译了一个 C 库,并编写了可以在交互式 Node.js shell:
中正确交互的 JS// script compiled by Emscripten
const _smaz = require("./_smaz");
var out_heap = _smaz['_malloc'](encoded.length * 8);
...
但是,当在我的应用程序中立即调用该函数时,_malloc
失败:
TypeError: Cannot read property 'apply' of undefined
at Object.a._malloc
即使添加 100 毫秒 setTimeout
也可以解决问题。看起来编译后的 Emscripten 东西是异步加载的,函数不能立即使用。
正确的处理方法是什么? Emscripten docs 建议在我的 "page" 加载后添加一个 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
编译器选项可以禁用异步 startup/loading 行为:-s BINARYEN_ASYNC_COMPILATION=0
和 -s SINGLE_FILE=1
。这解决了我的问题。
来自相关GitHub issue:
In general emscripten tries to do startup asynchronously for wasm, because it's what browsers can best optimize, and worse, Chrome currently has a limitation on the size of synchronous compilations (hopefully will be fixed soon). But you can force sync compilation with
-s BINARYEN_ASYNC_COMPILATION=0
.That still leaves fetching the wasm binary file. By default we fetch it asynchronously, but if you have a way to get it yourself before, you can set it on
Module['wasmBinary']
and we will just use that synchronously. Alternatively, #5296 will add an option to embed that file, making it available synchronously.