使用内存来获取字符串会产生不正确的结果

k29*_*k29 6 javascript webassembly assemblyscript

我从这里遵循解决方案: 如何从WebAssembly函数返回JavaScript字符串 ,这里: 如何从WebAssembly中的Rust返回字符串(或类似字符串)?

但是,当从内存中读取时,我没有得到预期的结果.

AssemblyScript文件,helloWorldModule.ts:

export function getMessageLocation(): string {
    return "Hello World";
 }
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

这将返回32的偏移量.最后产生一个过早开始的字符串,并在"Hello World"的每个字母之间有空格:

在此输入图像描述

但是,如果我将数组更改为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>
Run Code Online (Sandbox Code Playgroud)

然后我们得到正确的结果: 在此输入图像描述

为什么第一组代码不能像我提供的链接那样工作?为什么我需要更改它以使用Int16Array来摆脱"H"和"e"之间的空间?为什么我需要在偏移量中添加8个字节?

总之,这里究竟发生了什么?

编辑:另一个线索,如果我在UInt8阵列上使用TextDecoder,解码为UTF-16看起来比解码为UTF-8更正确: 在此输入图像描述 在此输入图像描述

k29*_*k29 0

AssemblyScript 使用 utf-16: https: //github.com/AssemblyScript/assemblescript/issues/43

此外,AssemblyScript 将字符串的长度存储在前 32 位或 64 位中。

这就是我的代码表现不同的原因。本文顶部链接中的示例适用于 C++ 和 Rust,它们的字符串编码方式不同