javascript - 如何从 WebAssembly 函数返回 JavaScript 字符串

标签 javascript webassembly

如何从 WebAssembly 函数返回 JavaScript 字符串?

以下模块可以用 C(++) 编写吗?

export function foo() {
  return 'Hello World!';
}

另外:我可以将其传递给 JS 引擎进行垃圾收集吗?

最佳答案

WebAssembly 本身并不支持字符串类型,而是支持 i32/i64/f32/f64 value types以及用于存储的 i8/i16

您可以使用以下方式与 WebAssembly 实例交互:

  • exports ,从 JavaScript 调用 WebAssembly,WebAssembly 返回单个值类型。
  • imports其中 WebAssembly 调用 JavaScript,具有任意数量的值类型(注意:必须在模块编译时知道计数,这不是数组,也不是可变参数)。
  • Memory.buffer ,这是一个 ArrayBuffer,可以使用(以及其他)Uint8Array 进行索引。

这取决于您想要做什么,但似乎直接访问缓冲区是最简单的:

const bin = ...; // WebAssembly binary, I assume below that it imports a memory from module "imports", field "memory".
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory({ initial: 2 }); // Size is in pages.
const instance = new WebAssembly.Instance(module, { imports: { memory: memory } });
const arrayBuffer = memory.buffer;
const buffer = new Uint8Array(arrayBuffer);

如果您的模块有 start function然后它在实例化时被执行。否则你可能会有一个你称之为的导出,例如instance.exports.doIt()

完成后,您需要获取内存中的字符串大小+索引,您也可以通过导出公开它:

const size = instance.exports.myStringSize();
const index = instance.exports.myStringIndex();

然后您可以从缓冲区中读取它:

let s = "";
for (let i = index; i < index + size; ++i)
  s += String.fromCharCode(buffer[i]);

请注意,我正在从缓冲区读取 8 位值,因此我假设字符串是 ASCII。这就是 std::string 将为您提供的内容(内存中的索引将是 .c_str() 返回的内容),但是要公开其他内容(例如 UTF-8),您需要需要使用支持UTF-8的C++库,然后自己从JavaScript读取UTF-8,获取码点,并使用String.fromCodePoint

您还可以依赖以 null 结尾的字符串,但我在这里没有这样做。

您还可以使用TextDecoder API一旦通过创建 ArrayBufferView 在浏览器中更广泛地使用它进入 WebAssembly.Memorybuffer(这是一个 ArrayBuffer)。

<小时/>

相反,如果您正在执行从 WebAssembly 登录到 JavaScript 之类的操作,那么您可以如上所述公开内存,然后从 WebAssembly 声明一个使用大小 + 位置调用 JavaScript 的导入。您可以将您的模块实例化为:

const memory = new WebAssembly.Memory({ initial: 2 });
const arrayBuffer = memory.buffer;
const buffer = new Uint8Array(arrayBuffer);
const instance = new WebAssembly.Instance(module, {
    imports: {
        memory: memory,
        logString: (size, index) => {
            let s = "";
            for (let i = index; i < index + size; ++i)
                s += String.fromCharCode(buffer[i]);
            console.log(s);
        }
    }
});

这里有一个警告,如果您增加内存(通过 JavaScript 使用 Memory.prototype.grow 或使用 grow_memory 操作码),则 ArrayBuffer 被阉割,您需要重新创建它。

<小时/>

关于垃圾回收:WebAssembly.Module/WebAssembly.Instance/WebAssembly.Memory都是JavaScript引擎收集的垃圾,但那是一把相当大的锤子。您可能需要 GC 字符串,但目前对于位于 WebAssembly.Memory 内的对象来说这是不可能的。我们已经讨论过adding GC support in the future .

关于javascript - 如何从 WebAssembly 函数返回 JavaScript 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41353389/

相关文章:

Rust wasm : How to access HTMLDocument from web-sys?

javascript - 如何找到 WebAssembly 缓冲区的地址并将其返回给 Javascript?

python - 在 BigQuery 中运行 python 函数

javascript - 如何检测故障并重置/重启 webassembly 模块?

javascript - 为什么 WebAssembly 这么慢?

javascript - 如何在AG-Grid中设置列的动态字段?

javascript - 仅当没有其他事件同时触发时才触发 Javascript 单击/触摸事件?

php - 从 PHP 变量中转义换行符(结束行)以供 Javascript 使用

javascript - 如何使 TypeScript 枚举限制为特定数字

javascript - 使用 Node.js 读写 vcard