如何在 JavaScript 中直接实例化 WebAssembly 模块

问题描述 投票:0回答:2

我见过的示例基本上表明了这一点:

fetch('simple.wasm').then(response =>
  response.arrayBuffer()
).then(bytes =>
  WebAssembly.instantiate(bytes, {})
).then(result =>
  result.instance.exports...
)

但我想在不发出额外 HTTP 请求的情况下完成此操作。想知道是否唯一的方法是这个(或者它的一些变体,这将有助于了解):

var binary = '...mywasmbinary...'
var buffer = new ArrayBuffer(binary.length)
var view = new DataView(buffer)
for (var i = 0, n = binary.length; i < n; i++) {
  var x = binary[i]
  view.setInt8(i * 8, x)
}

想知道我是否需要担心字节顺序或类似的问题。

或者也许用

URL
和斑点做一些事情可能会更好,我不确定。

javascript webassembly
2个回答
11
投票

是的,你是对的,为了内联 wasm 模块并避免 HTTP 请求,你必须执行某种编码。我建议使用 Base64 编码的字符串,因为它们是最紧凑的形式。

您可以按如下方式编码:

const readFileSync = require('fs').readFileSync;

const wasmCode = readFileSync(id);
const encoded = Buffer.from(wasmCode, 'binary').toString('base64');

然后您可以按如下方式加载模块:

    var encoded = "... contents of encoded from above ...";

    function asciiToBinary(str) {
      if (typeof atob === 'function') {
        // this works in the browser
        return atob(str)
      } else {
        // this works in node
        return new Buffer(str, 'base64').toString('binary');
      }
    }

    function decode(encoded) {
      var binaryString =  asciiToBinary(encoded);
      var bytes = new Uint8Array(binaryString.length);
      for (var i = 0; i < binaryString.length; i++) {
          bytes[i] = binaryString.charCodeAt(i);
      }
      return bytes.buffer;
    }

    var module = WebAssembly.instantiate(decode(encoded), {});

0
投票

谢谢科林。这解决了我尝试将 WASM 模块上传到 NPM 的问题。为此,我必须将您的答案分成两个文件:“导出”和“导入”。忽略浏览器兼容性,只关注 Node,我的解决方案最终是这样的:

const readFileSync = require('fs').readFileSync
const writeFile = require('fs').writeFileSync;

const wasmCode = readFileSync("./public/wasm/main.wasm");
const encoded = Buffer.from(wasmCode, 'binary').toString('base64');

function exportToJson(encoded){
    json = "\""+encoded+"\""
    writeFile("b64wasm.json", json, err => {
    if (err) {
      console.error(err);
    }
    // file written successfully
  });
}

exportToJson(encoded)

wasmBin = require("./b64wasm.json")

const crypto = require("crypto").webcrypto;
globalThis.crypto = crypto;
require('./public/wasm/wasm_exec.js');

function decode(encoded) {
    var binaryString =  Buffer.from(encoded, 'base64').toString('binary');
    var bytes = new Uint8Array(binaryString.length);
    for (var i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes.buffer;
}

function loadWebAssembly() {
const go = new Go();
const importObject = go.importObject;
WebAssembly.instantiate(decode(wasmBin), importObject).then((results) => {
        const instance = results.instance
        go.run(instance);
        console.log("arrival One")
    });
}
loadWebAssembly()
setTimeout(()=>{
    let a = Math.floor(Math.random()*100)
    let b = Math.floor(Math.random()*100)
    const sum = addTwoNumbers(a,b);
    console.log("arrived two: ", sum)
},100)
© www.soinside.com 2019 - 2024. All rights reserved.