【问题标题】:How to wrap with webassembly the c funtion printf with js console.log function?如何用 webassembly 用 js console.log 函数包装 c 函数 printf?
【发布时间】: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


【解决方案1】:

WebAssembly 不直接支持字符串类型 - 因此,当编译 printf("test") 语句时,"test" 文字会转换为对保存实际字符串的线性内存中地址的引用。

您必须自己弄清楚如何执行解引用/编码/解码。有关详细信息,请参阅以下内容:

How can I return a JavaScript string from a WebAssembly function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多