WebAssembly:从JavaScript中的参数(带有内存地址)获取字符串的正确方法

时间:2018-07-27 16:47:41

标签: javascript web webassembly

我试图了解C代码到WebAssembly和JavaScript互操作的转换在后台如何工作。而且我在从函数参数获取简单字符串时遇到问题。

我的程序是一个简单的Hello World,我试图“模拟” printf / puts

或多或少我想构建的C等效项:

int main() {
  puts("Hello World\n");
}

您可以看到一个有效的示例here

目前,我最好的主意是一次读取16位内存块(因为wasm似乎以16位间隔分配它们)并检查空终端。

function get_string(memory, addr) {
  var length = 0;

  while (true) {
    let buffer = new Uint8Array(memory.buffer, addr, 16);
    let term = buffer.indexOf(0);

    length += term == -1 ? 16 : term;

    if (term != -1) break;
  }

  const strBuf = new Uint8Array(memory.buffer, addr, length);
  return new TextDecoder().decode(strBuf);
}

但这似乎很笨拙。如果您仅知道起始地址,是否有更好的方法从内存中读取字符串?

真的有必要一次只读取16位块吗? 创建内存的类型化数组算作访问整个内存时,我找不到任何信息,或者仅当我尝试从数组中获取数据时才会发生这种情况。

1 个答案:

答案 0 :(得分:3)

WebAssembly在64k页中分配内存。也许这就是16位的来源,因为16位可以寻址64 KB。但是,这与手头的任务无关,因为WebAssembly内存只是一个连续的地址空间,所以memory对象和给定大小的ArrayBuffer之间并没有太大的区别。完全没有。

一次也不需要16字节的窗口(以某种方式16位变成16字节)。

您可以简单地执行此操作,而不会降低性能,并可以通过以下方式创建缓冲区其余部分的视图:

function get_string(memory, addr) {
  let buffer = new Uint8Array(memory.buffer, addr, memory.buffer.byteLength - addr);
  let term = buffer.indexOf(0);

  return new TextDecoder().decode(buffer.subarray(0, term));
}