首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将JS中的ArrayBuffer传递给AssemblyScript/Wasm?

如何将JS中的ArrayBuffer传递给AssemblyScript/Wasm?
EN

Stack Overflow用户
提问于 2019-02-18 06:14:56
回答 1查看 3.2K关注 0票数 7

我有一段非常简单的Typescript代码,它解析特定的数据格式,输入是一个UInt8Array。我已经尽可能地对其进行了优化,但我认为这个相当简单的解析器的运行速度应该比我让它作为JS运行的速度快。我想尝试使用AssemblyScript在web汇编中编写它,以确保我不会遇到Javascript引擎的任何怪癖。

正如我现在所认识到的,我不能简单地将一个TypedArray传递给Wasm并让它自动工作。据我所知,我可以传递一个指向数组的指针,并且应该能够直接从Wasm访问它,而不需要复制该数组。但我不能让这个和AssemblyScript一起工作。

下面是一个最小的示例,它显示了我如何无法将ArrayBuffer传递给Wasm。

设置Wasm导出的代码主要来自自动生成的样板:

代码语言:javascript
复制
const fs = require("fs");
const compiled = new WebAssembly.Module(
  fs.readFileSync(__dirname + "/build/optimized.wasm")
);
const imports = {
  env: {
    abort(msgPtr, filePtr, line, column) {
      throw new Error(`index.ts: abort at [${line}:${column}]`);
    }
  }
};
Object.defineProperty(module, "exports", {
  get: () => new WebAssembly.Instance(compiled, imports).exports
});

下面的代码调用WASM,index.js是上面的粘合代码。

代码语言:javascript
复制
const m = require("./index.js");
const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
const result = m.parse(data.buffer);

编译成WASM的AssemblyScript如下所示:

代码语言:javascript
复制
import "allocator/arena";

export function parse(offset: usize): number {
  return load<u8>(offset);
}

当我执行该代码时,我得到一个"RuntimeError:内存访问越界“。

主要的问题是,我从Wasm中得到的错误根本不能帮助我自己解决这个问题。我显然遗漏了幕后实际工作的一些主要方面。

我如何使用AssemblyScript将TypedArray或ArrayBuffer从JS传递到Wasm?

EN

回答 1

Stack Overflow用户

发布于 2019-02-18 22:51:03

在AssemblyScript中,有许多方法可以从内存中读取数据。获取此数据的最快、最快的方法是在模块的函数导入中使用链接函数来返回指向数据本身的指针。

代码语言:javascript
复制
let myData = new Float64Array(100); // have some data in AssemblyScript

// We should specify the location of our linked function
@external("env", "sendFloat64Array")
declare function sendFloat64Array(pointer: usize, length: i32): void;

/**
 * The underlying array buffer has a special property called `data` which
 * points to the start of the memory.
 */
sendFloat64Data(myData.buffer.data, myData.length);

然后在JavaScript中,我们可以在链接函数中使用Float64Array构造函数直接返回值。

代码语言:javascript
复制
/**
 * This is the fastest way to receive the data. Add a linked function like this.
 */
imports.env.sendFloat64Array = function sendFloat64Array(pointer, length) {
  var data = new Float64Array(wasmmodule.memory.buffer, pointer, length);
};

然而,有一种更清晰的方法来获取数据,它涉及从AssemblyScript返回一个引用,然后使用AssemblyScript加载器。

代码语言:javascript
复制
let myData = new Float64Array(100); // have some data in AssemblyScript

export function getData(): Float64Array {
  return myData;
}

然后在JavaScript中,我们可以使用AssemblyScript提供的ASUtil加载器。

代码语言:javascript
复制
import { instantiateStreaming } from "assemblyscript/lib/loader";

let wasm: ASUtil = await instantiateStreaming(fetch("myAssemblyScriptModule.wasm"), imports);

let dataReference: number = wasm.getData();
let data: Float64Array = wasm.getArray(Float64Array, dataReference);

出于代码清晰的原因,我强烈建议使用第二个示例,除非性能是绝对关键的。

祝你的AssemblyScript项目好运!

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54738197

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档