Как записать строку в память в WebAssembly - PullRequest
0 голосов
/ 06 июля 2018

Я начал работать так:

// example.wast
(module
  (memory (export "mem") 1))

// example.js
WebAssembly.instantiateStreaming(fetch('example.wasm'), {}).then(mod => {
  var exports = mod.instance.exports
  var i8 = new Uint8Array(exports.mem)
  var ra = 100
  var rb = 500
  var rc = 1000
  var rd = 1200
  var re = 2000
  exports.copy(0, ra)
  exports.copy(ra, rb)
  exports.copy(rb, rc)
  exports.copy(rc, rd)
  exports.copy(rd, re)
  console.log(ra, getString(ra, i8))
  console.log(rb, getString(rb, i8))
  console.log(rc, getString(rc, i8))
  console.log(rd, getString(rd, i8))
  console.log(re, getString(re, i8))
})

function getString(index, buffer) {
  var s = ''
  for (var i = index; i < index + size; i++) {
    s += String.fromCharCode(buffer[i])
  }
  return s
}

Но чтобы реализовать эту функцию copy, мне сначала нужно загрузить строки в память WebAssembly. Интересно, как я это делаю (используя как можно меньше JS, используя вместо этого в основном WebAssembly). Хотите знать, если вы можете сделать это:

exports.loadString(index, 'Hello World', i8)

Или, если нет, вы должны сделать что-то вроде этого:

function loadString(index, string, buffer) {
  for (var i = 0, n = string.length; i < n; i++) {
    buffer[index + i] = string[i]
  }
}

Или еще лучше:

function loadString(index, string, buffer) {
  for (var i = 0, n = string.length; i < n; i++) {
    exports.loadChar(index + i, string[i])
  }
}

Хотите знать, как это сделать exports.loadChar или exports.loadString в WebAssembly, где он загружает в определенное место в памяти строку.

Я бы хотел избежать использования JS, т.е. buffer[index + i] = string[i]. Возможно, существует способ динамической загрузки в сегмент data, который бы позволял exports.loadString.

1 Ответ

0 голосов
/ 06 июля 2018

WebAssembly не имеет своих собственных служебных функций для чтения / записи в линейную память, поэтому нет экспортируемой функции exports.loadString.

WebAssembly экспортирует ссылку на саму линейную память, которую вы можете читать / записывать как типизированный массив. Вы уже получили ссылку на это здесь:

var i8 = new Uint8Array(exports.mem)

Это создает байтовый массив, который позволяет вам читать / записывать в линейную память, которая была экспортирована из вашего модуля с именем mem. Вам нужно закодировать вашу строку и записать ее в этот массив:

var encoder = new TextEncoder();
var encodedString = encoder.encode(str);

var i8 = new Uint8Array(exports.mem)

// Copy the UTF-8 encoded string into the WASM memory.
i8.set(encodedString);
...