C/C++编译成.wasm文件,并使用javascript调用接口

一、C/C++编译成.wasm

0.背景

准备好本地编译环境Emscripten,使用emcc命令编译的.wasm文件在js里面调用时报这个错误:

CompileError: Wasm decoding failedResult = expected magic word 00 61 73 6d, found 42 43 c0 ……

没找到处理办法,但是找到了一种更简单的方法–使用WebAssembly Studio在线编译。

1、如果只是需要一个.wasm文件,创建Empty C Project

在这里插入图片描述

2、main.js和main.html也可以删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DYrmhl1D-1590498410522)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1590496699150.png)]

3、在main.c中编写c代码,注意每一个函数上面需要加WASM_EXPORT

在这里插入图片描述

4、可以右键edit更改输入、输出文件名称,但是注意build.ts文件输入、输出文件需要同步

在这里插入图片描述
在这里插入图片描述

5、最后注意保存文件!再build就编译生成了.wasm文件

在这里插入图片描述
在这里插入图片描述

二、javascript加载.wasm文件,调用接口

1、右键刚刚生成的.wasm文件download下载

在这里插入图片描述

2、测试代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>Compile C to WebAssembly</h1>
<p>The test result can be found in console.</p>

<script>
    function loadWebAssembly(path) {
        return fetch(path)                     // 加载文件
            .then(res => res.arrayBuffer())    // 转成 ArrayBuffer
            .then(WebAssembly.instantiate)     // 编译 + 实例化
            .then(mod => mod.instance)         // 提取生成都模块
    }

    loadWebAssembly('./math.wasm')
        .then(instance => {
            const add = instance.exports.add;
            const sub = instance.exports.sub;
            const mul = instance.exports.mul;
            const dev = instance.exports.dev;

            console.log('1+1 =', add(1, 1));
            console.log('1-1 =', sub(1, 1));
            console.log('1×6 =', mul(1, 6));
            console.log('9÷3 =', dev(9, 3));
        });
    
</script>
</body>
</html>

3、运行结果

在这里插入图片描述

4、如果失败,将第2步的loadWebAssembly换成这个

    /**
     * 如果你直接使用上边那个 loadWebAssembly 函数,有可能会执行失败,因为在 wasm 文件里,可能还会引入一些环境变量,
     * 在实例化的同时还需要初始化内存空间和变量映射表,也就是 WebAssembly.Memory 和 WebAssembly.Table。
     * @param {String} path wasm 文件路径
     * @param {Object} imports 传递到 wasm 代码中的变量
     * @returns {Promise<WebAssembly.Instance>}
     */
    function loadWebAssembly(path, imports = {}) {
        return fetch(path)
            .then(response => response.arrayBuffer())
            .then(buffer => WebAssembly.compile(buffer))
            .then(module => {
                imports.env = imports.env || {};

                // 开辟内存空间
                imports.env.memoryBase = imports.env.memoryBase || 0;
                if (!imports.env.memory) {
                    imports.env.memory = new WebAssembly.Memory({initial: 256})
                }

                // 创建变量映射表
                imports.env.tableBase = imports.env.tableBase || 0;
                if (!imports.env.table) {
                    // 在 MVP 版本中 element 只能是 "anyfunc"
                    imports.env.table = new WebAssembly.Table({initial: 0, element: 'anyfunc'})
                }

                // 创建 WebAssembly 实例
                return new WebAssembly.Instance(module, imports)
            })
    }

5、// TODO 引入了第三方库的c文件编译成.wasm(求助…)

三、参考

WebAssembly 实践:如何写代码

猜你喜欢

转载自blog.csdn.net/m0_46439030/article/details/106365076