Lance Pollard
Lance Pollard

Reputation: 79258

How to Write a String to Memory in WebAssembly

I started off working like this:

// 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
}

But in order to implement that copy function, I first need to load strings into the WebAssembly memory. Wondering how I do that (using as little JS as possible, using mostly WebAssembly instead). Wondering if you can do this:

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

Or if not, you have to do something like this instead:

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

Or better yet:

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

Wondering how to do this exports.loadChar or exports.loadString in WebAssembly, where it loads to a specific place in memory the string.

I would like to avoid using JS, i.e. buffer[index + i] = string[i]. Perhaps there is a way to dynamically load into the data segment, which would allow for exports.loadString.

Upvotes: 3

Views: 1515

Answers (1)

ColinE
ColinE

Reputation: 70142

WebAssembly does not have any of its own utility functions for reading / writing to linear memory, therefore there is no exported exports.loadString function.

WebAssembly exports a reference to linear memory itself, which you can read / write to as a typed array. You've already obtained a reference to it here:

var i8 = new Uint8Array(exports.mem)

This creates a byte array that allows you to read / write to the linear memory that was exported from your module with the name mem. You need to encode your string and write it to this array:

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

Upvotes: 2

Related Questions