WASM reactmodule解析失败:未检测到魔术头

IT技术 reactjs webassembly
2021-05-24 18:56:49

我正在尝试在 React 项目中加载一个简单的 Web 程序集module。wasm module是用MODULARIZE选项编译的

文档中,我尝试将其合并到我的代码中,如下所示:

fetch('./my-library.wasm')
  .then(response => response.arrayBuffer())
  .then(bytes => WebAssembly.instantiate(bytes))
  .then(results => {
    console.log("do something");
  });

理想情况下,我希望将结果存储在其中,state以便我可以在整个代码中访问该module(替换控制台日志)。

不幸的是,这给了我错误

Unhandled Rejection (CompileError): wasm validation error: at offset 4: failed to match magic number

我错过了什么?没有编译MODULARIZE也会出现此错误。

2个回答

到目前为止,要.wasm在任何浏览器中使用,您必须将其托管在具有适当 MIME 内容类型的任何简单服务器中,例如在 chrome 网络选项卡中,您必须看到这种响应

在此处输入图片说明

然后只有 WASM 在您的fetch('./my-library.wasm')代码中被视为正确的响应

可以参考官方文档Emscripten

它清楚地表明

不幸的是,一些浏览器(包括 Chrome、Safari 和 Internet Explorer)不支持 file:// XHR 请求,并且无法加载 HTML 所需的额外文件(如 .wasm 文件,或下面提到的打包文件数据) . 对于这些浏览器,您需要使用网络服务器来提供文件。最简单的方法是使用 python SimpleHTTPServer(在当前目录中执行 python -m SimpleHTTPServer 8080 然后打开http://localhost:8080/hello.html)。

我可以看到您正在使用 react,所以很明显您确实使用了本地 Node.JS 服务器,您需要将二进制文件与不应该是./. 它应该是其他一些文件夹,在哪里.cssimages在那里

重要说明:响应必须具有application/wasm

用我的module尝试了这个这个,但他们没有工作,所以尝试将 wasm 文件直接放在公共文件夹中并从那里获取它(另见:this)。它需要针对 wasm module的用例(内存设置等)进行一些调整。我的具体情况现在看起来像这样

componentDidMount() {
  this.loadWasm();
}

loadWasm() {
  const path = process.env.PUBLIC_URL + '/my-library.wasm';
  const importObject = {
    env: {
      memoryBase: 0,
      tableBase: 0,
      memory: new WebAssembly.Memory({initial: 256, maximum: 1024}),
      table: new WebAssembly.Table({initial: 256, element: 'anyfunc'}),
      __assert_fail: function() {
        // todo
      },
      emscripten_resize_heap: function() {
        // todo
      },
      emscripten_memcpy_big: function() {
        // todo
      },
      setTempRet0: function() {
        // todo
      }
    }
  };
  WebAssembly.instantiateStreaming(fetch(path), importObject).then(obj => {
    // do stuff
  });
}

编辑

由于 react 的路由问题,我在从其 javascript 包装器 (egaout.js) 获取 wasm 时遇到了幻数错误。最后,我决定将 javascript 作为依赖项包含在 index.html 文件中并不那么麻烦。这样做的好处是不必与 webpack 和 webpack 混淆,而不必与 emcc 生成的 js 混淆。此外,不直接加载 wasm module,emcc 生成的 js 负责设置importObject.