【发布时间】:2019-08-01 12:30:11
【问题描述】:
如何用 console.log 包装 printf() 函数?我想编写一个小型 webassembly 演示,但无法解释以下 js 控制台输出。我用 Clang 将 C 代码编译成 wasm 文件。
C 代码:
#include <stdio.h>
int main(void)
{
printf ("test");
return 0;
}
JS代码:
const config = {
env: {
memory_base: 0,
table_base: 0,
memory: new WebAssembly.Memory({
initial: 256,
}),
table: new WebAssembly.Table({
initial: 0,
element: 'anyfunc',
}),
printf: msg => console.log(msg),
}
}
fetch('test.wasm')
.then(response =>
response.arrayBuffer()
)
.then(bytes => {
return WebAssembly.instantiate(bytes, config);
})
.then(results => {
var { main } = results.instance.exports;
main();
});
控制台输出始终为:“1024”,与 printf() 输入参数无关。但我想得到字符串“test”作为输出。如何解释这个结果?它是指向内存地址的指针吗?当我使用 printf('a') 时,我得到 97 作为控制台输出,即字符的 ascii 表示。
解决方案:
let buffer;
const config = {
env: {
memory_base: 0,
table_base: 0,
memory : new WebAssembly.Memory({ initial: 256}),
table: new WebAssembly.Table({
initial: 0,
element: 'anyfunc',
}),
printf: index=> {
let s = "";
while(true){
if(buffer[index] !== 0){
s += String.fromCharCode(buffer[index]);
index++;
}else{
console.log(s);
return;
}
}
}
}
};
fetch(url)
.then(response =>{
return response.arrayBuffer();
})
.then(bytes => {
return WebAssembly.instantiate(bytes, config);
})
.then(results => {
let { main } = results.instance.exports;
buffer = new Uint8Array(results.instance.exports.memory.buffer);
main();
});
【问题讨论】:
-
你为什么不直接使用 Emscripten?
-
我知道 Emscripten 有 cwrap/ccall 函数,但我必须使用 Clang 编译器。这是客户规格:)
-
Emscripten 使用 clang/LLVM 作为后端。我的建议是你会想在某个时候使用 Emscripten,否则你必须重新实现每个 C 库和运行时......
-
无论如何,你能发布你的clang命令吗?包括 clang 编译标志。
-
好的,我尝试将编译器更改为 Emscripten,但目前我只是使用预定义的 docker 环境,里面有 clang。容器内的命令是“clang --target=wasm32 -Wl,--initial-memory=131072,--allow-undefined,--export=main,--no-threads,--strip-all,-- no-entry -O2 -s -o test.wasm test.c" 一切都正确编译和运行,我只是尝试用 c/js 函数包装做一些实验。
标签: webassembly