Работа с памятью для извлечения строки дает неверный результат - PullRequest
0 голосов
/ 17 октября 2018

Я следую решениям отсюда: Как я могу вернуть строку JavaScript из функции WebAssembly и здесь: Как вернуть строку (или аналогичную) из Rust в WebAssembly?

Однако при чтении из памяти я не получаю желаемых результатов.

Файл AssemblyScript, helloWorldModule.ts:

export function getMessageLocation(): string {
    return "Hello World";
 }

index.html:

 <script>
    fetch("helloWorldModule.wasm").then(response =>
    response.arrayBuffer()
   ).then(bytes =>
      WebAssembly.instantiate(bytes, {imports: {}})
    ).then(results => { 
        var linearMemory = results.instance.exports.memory;
        var offset = results.instance.exports.getMessageLocation();
        var stringBuffer = new Uint8Array(linearMemory.buffer, offset, 11);

        let str = '';
        for (let i=0; i<stringBuffer.length; i++) {
            str += String.fromCharCode(stringBuffer[i]);
        }
    debugger;
    });
  </script>

Это возвращает смещение 32. И, наконец, возвращает строку, которая начинается слишком рано и имеет пробелы между каждой буквой «Hello World»:

enter image description here

Однако, если я изменю массив на Int16Array и добавлю 8 к смещению (которое было 32), чтобы смещение составило 40. Примерно так:

  <script>
    fetch("helloWorldModule.wasm").then(response =>
      response.arrayBuffer()
    ).then(bytes =>
      WebAssembly.instantiate(bytes, {imports: {}})
    ).then(results => { 
        var linearMemory = results.instance.exports.memory;
        var offset = results.instance.exports.getMessageLocation();
        var stringBuffer = new Int16Array(linearMemory.buffer, offset+8, 11);

        let str = '';
        for (let i=0; i<stringBuffer.length; i++) {
            str += String.fromCharCode(stringBuffer[i]);
        }
        debugger;
    });
  </script>

Тогда мы получимправильный результат: enter image description here

Почему первый набор кода не работает так, как предполагалось в приведенных мною ссылках?Почему мне нужно изменить его, чтобы он работал с Int16Array, чтобы избавиться от пробела между "H" и "e", например?Зачем мне добавлять 8 байтов к смещению?

Итак, что здесь происходит?

Редактировать: Еще одна подсказка, если я использую TextDecoder в массиве UInt8, декодирование как UTF-16 выглядит более правильным, чем декодирование как UTF-8: enter image description here enter image description here

1 Ответ

0 голосов
/ 18 октября 2018

AssemblyScript использует utf-16: https://github.com/AssemblyScript/assemblyscript/issues/43

Кроме того, AssemblyScript сохраняет длину строки в первых 32 или 64 битах.

Вот почему мой код ведет себя по-разному.Примеры в ссылках в верхней части этого поста были для C ++ и Rust, которые по-разному кодируют строки

...