如何加载存储在子目录中的.wasm文件?

Kil*_*ner 6 javascript emscripten webassembly

我正在尝试一个简单的例子,用JavaScript调用编译为.wasm的C函数.

这是counter.c文件:

#include <emscripten.h>

int counter = 100;

EMSCRIPTEN_KEEPALIVE
int count() {  
    counter += 1;
    return counter;
}
Run Code Online (Sandbox Code Playgroud)

我用它编译了它emcc counter.c -s WASM=1 -o counter.js.

我的main.jsJavaScript文件:

Module['onRuntimeInitialized'] = onRuntimeInitialized;
const count = Module.cwrap('count ', 'number');

function onRuntimeInitialized() {
    console.log(count());
}
Run Code Online (Sandbox Code Playgroud)

我的index.html文件只加载正文中的两个.js文件,没有别的:

<script type="text/javascript" src="counter.js"></script>
<script type="text/javascript" src="main.js"></script>
Run Code Online (Sandbox Code Playgroud)

它工作正常/打印101到控制台,但当我将counter.c文件移动到一个wasm子目录,用emscripten重新编译并更新script标签src="wasm/counter.js",counter.js脚本尝试counter.wasm从根目录而不是wasm子目录加载,我得到错误:

counter.js:190 failed to asynchronously prepare wasm: failed to load wasm binary file at 'counter.wasm'

我做了一些研究,但我没有找到任何方法告诉emscripten让生成的.js文件从同一个子目录加载.wasm.

Hug*_*ira 7

正如ColinE在另一个答案中所解释的那样,您应该查看emcc编译器生成的integrateWasmJS()函数(counter.js).该函数的主体最近已更改,现在看起来像这样:

function integrateWasmJS() {
    ...
    var wasmBinaryFile = 'counter.wasm';

    if (typeof Module['locateFile'] === 'function') {
        ...
        if (!isDataURI(wasmBinaryFile)) {
          wasmBinaryFile = Module['locateFile'](wasmBinaryFile);
        }
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,那么您应该向全局Module变量添加"locateFile"函数.因此,在HTML中,您可以在导入counter.js文件之前添加以下代码段:

<script>
  var Module = {
    locateFile: function(s) {
      return 'wasm/' + s;
    }
  };
</script> 
Run Code Online (Sandbox Code Playgroud)


Col*_*inE 5

如果您查看 emscripten 创建的生成的 'loader' 文件,它具有integrateWasmJS如下功能:

function integrateWasmJS(Module) {
  var method = Module['wasmJSMethod'] || 'native-wasm';
  Module['wasmJSMethod'] = method;

  var wasmTextFile = Module['wasmTextFile'] || 'hello.wast';
  var wasmBinaryFile = Module['wasmBinaryFile'] || 'hello.wasm';
  var asmjsCodeFile = Module['asmjsCodeFile'] || 'hello.temp.asm.js';

  ...
}
Run Code Online (Sandbox Code Playgroud)

您可以看到wasmBinaryFile指示二进制文件的位置。如果未设置,则提供默认值。

看起来您应该能够在您的main.js文件中覆盖它,如下所示:

Module['wasmBinaryFile'] = 'wasm/counter.wasm';
Run Code Online (Sandbox Code Playgroud)