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

标签 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 位 block 吗? 如果创建类型化的内存数组算作访问整个内存,或者这仅在我尝试从数组中获取数据时才会发生,我找不到任何信息。

最佳答案

WebAssembly 以 64k 页为单位分配内存。也许这就是 16 位的来源,因为 16 位可以寻址 64 kbytes。然而,这与手头的任务无关,因为 WebAssembly 内存只是一个连续的地址空间,memory 对象和 ArrayBuffer 之间没有太大区别给定尺寸,如果有的话。

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

您可以在没有任何性能损失的情况下简单地做到这一点,并通过以下方式创建缓冲区其余部分的 View :

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));
}

关于javascript - WebAssembly:从 JavaScript 中的参数(带有内存地址)获取字符串的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51562325/

相关文章:

javascript - 将每个对象的 X,Y 坐标获取到 Fabric.js 中的数组中

javascript - 使用 DOM 的 Javascript 中的多列表

ruby-on-rails - 使用 ruby​​ on Rails 向静态网站添加功能

string - 如何将 "Hello World"加载到 WebAssembly 中的 `.data` 部分

debugging - 如何调试 Razor 页面中的嵌入式代码?

javascript - 将图节点的相对位置投影到绝对坐标

javascript - 访问 Angular Directive(指令)中的嵌套节点

html - 如何让文本在某一点停止并转到下一行?

javascript - jQuery 变量对象?

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