如何从WebAssembly函数返回JavaScript字符串?
下列模块可以用C(++)编写吗?
export function foo() { return 'Hello World!'; }
另外:我可以将其传递给JS引擎进行垃圾回收吗?
WebAssembly本身不支持字符串类型,它,而支撑件i32/i64/f32/f64值类型以及i8/i16用于存储。
i32
i64
f32
f64
i8
i16
这取决于您要执行的操作,但似乎直接访问缓冲区是最简单的:
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功能,那么它将在实例化时执行。否则,您可能会调用一个导出,例如instance.exports.doIt()。
start
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。
std::string
.c_str()
String.fromCodePoint
您还可以依靠以null终止的字符串,我在这里没有这样做。
您也可以使用TextDecoderAPI,一旦它获得更广泛的浏览器中创建一个ArrayBufferView到WebAssembly.Memory的buffer(这是ArrayBuffer)。
TextDecoder
ArrayBufferView
WebAssembly.Memory
buffer
ArrayBuffer
相反,如果您正在执行从WebAssembly到JavaScript的登录等操作,则可以公开Memory上述内容,然后从WebAssembly声明一个导入,该导入以size+ position调用JavaScript。您可以将模块实例化为:
Memory
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的JavaScriptMemory.prototype.grow或使用grow_memory操作码),则内存将ArrayBuffer被清除,您需要重新创建内存。
Memory.prototype.grow
grow_memory
垃圾收集器:WebAssembly.Module/WebAssembly.Instance/WebAssembly.Memory是由JavaScript引擎收集到的所有垃圾,但是这是一个相当大的锤子。您可能希望使用GC字符串,而对于位于中的对象,目前尚无法实现WebAssembly.Memory。
WebAssembly.Module
WebAssembly.Instance