我试图了解C代码到WebAssembly和JavaScript互操作的转换在后台如何工作。而且我在从函数参数获取简单字符串时遇到问题。
我的程序是一个简单的Hello World,我试图“模拟” printf
/ puts
。
或多或少我想构建的C等效项:
int main() {
puts("Hello World\n");
}
您可以看到一个有效的示例here。
目前,我最好的主意是一次读取16位内存块(因为wasm似乎以16位间隔分配它们)并检查空终端。
function get_string(memory, addr) {
var length = 0;
while (true) {
let buffer = new Uint8Array(memory.buffer, addr, 16);
let term = buffer.indexOf(0);
length += term == -1 ? 16 : term;
if (term != -1) break;
}
const strBuf = new Uint8Array(memory.buffer, addr, length);
return new TextDecoder().decode(strBuf);
}
但这似乎很笨拙。如果您仅知道起始地址,是否有更好的方法从内存中读取字符串?
真的有必要一次只读取16位块吗? 创建内存的类型化数组算作访问整个内存时,我找不到任何信息,或者仅当我尝试从数组中获取数据时才会发生这种情况。
答案 0 :(得分:3)
WebAssembly在64k页中分配内存。也许这就是16位的来源,因为16位可以寻址64 KB。但是,这与手头的任务无关,因为WebAssembly内存只是一个连续的地址空间,所以memory
对象和给定大小的ArrayBuffer
之间并没有太大的区别。完全没有。
一次也不需要16字节的窗口(以某种方式16位变成16字节)。
您可以简单地执行此操作,而不会降低性能,并可以通过以下方式创建缓冲区其余部分的视图:
function get_string(memory, addr) {
let buffer = new Uint8Array(memory.buffer, addr, memory.buffer.byteLength - addr);
let term = buffer.indexOf(0);
return new TextDecoder().decode(buffer.subarray(0, term));
}