javascript 汇编脚本:使用i32但不使用字符串的函数

6pp0gazn  于 2023-03-16  发布在  Java
关注(0)|答案(1)|浏览(127)

我有一个AssemblyScript函数,它返回给定的任何string,以及相应的代码,以便在NodeJS中导入和运行它:

程序集脚本:

export function parse(x: string): string {
  return x;
}

** NodeJS :**

import { readFileSync } from 'fs';

export default async function compile(raw) {
  return WebAssembly.instantiate(
    readFileSync('./src/.assembly/engine.wasm') // The WASM file containing compiled AssemblyScript
  ).then(mod => {
    const { parse } = mod.instance.exports;
    return parse(raw);
  });
}

compile('test').then(res => {
  console.log(res);
});

但是,当运行此代码时,它会返回一个关于imports参数不存在的错误:

航站楼:

node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[TypeError: WebAssembly.instantiate(): Imports argument must be present and must be an object]

Node.js v18.15.0
error Command failed with exit code 1.

奇怪的是,如果使用i32而不是string,代码运行正常:

程序集脚本:

export function parse(x: i32): i32 {
  return x;
}

** NodeJS :**

import { readFileSync } from 'fs';

export default async function compile(raw) {
  return WebAssembly.instantiate(
    readFileSync('./src/.assembly/engine.wasm') // The WASM file containing compiled AssemblyScript
  ).then(mod => {
    const { parse } = mod.instance.exports;
    return parse(raw);
  });
}

compile(44).then(res => {
  console.log(res);
});

航站楼:

44

我怎样才能修正代码使其也能处理字符串呢?

oo7oh9g9

oo7oh9g91#

您的准时错误来自这样一个事实,即当涉及字符串时,AssemblyScript做了很多工作来适应它们,因为它们不在WebAssembly规范中,这使得i32s更容易使用。
如果您使用strings命令来执行以下操作,就可以看到这一点。
i32:

$ strings release.wasm
parse
memory
sourceMappingURL
./release.wasm.map

字符串:

$ strings release.wasm
abort
__new
__pin
__unpin
__collect
__rtti_base
memory
parse
A|q!
...many more lines later...
A}q6
A|qA
sourceMappingURL
./release.wasm.map

因此,WebAssembly.intantiate抱怨的首先是缺少imports对象,其次是缺少它所需的abort函数。
幸运的是,对于一个解决方案来说,你不需要担心这些,AssemblyScript loader会自动为你做一些事情,你可以用它来示例化模块,而不是WebAssembly.instantiate函数:

import { readFileSync } from 'fs';
import loader from "@assemblyscript/loader";

export default function compile(raw) {
  let wasmModule = loader.instantiateSync(readFileSync('./build/release.wasm'), {});
  const { __newString, __getString } = wasmModule.exports;
  return __getString(wasmModule.exports.parse(__newString(raw)));
}

console.log(compile('test'));

除此之外,遗憾的是,与来自javascript的字符串通信的方法仍然是使用__newString__getString,它们为您完成转换WebAssembly地址的工作,因为WebAssembly没有字符串的概念。
还有一点好消息

$ node index.js 
test

代码现在可以正常工作。

相关问题