14行JavaScript教你使用WebAssembly
Posted 前端之巅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了14行JavaScript教你使用WebAssembly相关的知识,希望对你有一定的参考价值。
要编写一个可以在浏览器中运行的 WebAssembly 应用,主要分为两个部分,可编译为 WebAssembly 的源语言和加载用的 javascript。
整个流程大致可以分为:
编写代码:用常用语言编写一个工程,可以是 C、C++、Rust 等。其他各种语言编译成 WebAssembly 可以参照这里。
编译:将源码编译成 WebAssembly 的 wasm 文件。
引入:将之前生成的的 wasm 文件引入到前端工程中。
实例化:编写一段异步 JavaScript 代码加载和实例化 wasm 文件,使其他 JavaScript 文件可以无障碍使用。
当然,这只是一个非常简化的流程,但是对于诸如本文的示例项目已经足够。首先,我们会使用 C++ 编写一个简单的函数,然后使用在线工具将其编译成 wasm 文件(这样我们不用下载和安装任何编译工具),最后通过 14 行 JavaScript 代码加载并实例化。
上述过程完成之后,我们就能够通过 JavaScript 代码来调用之前通过 C++ 编写的函数了,是不是很神奇?
首先我们会编写一个 C++ 函数,当然了,前面提到过,这里不需要使用任何本地的编译链。取而代之的是一个 WebAssembly Explorer 的工具。它是一个类似 CodePen 的工具,可以左侧一列贴入 C++ 代码,编译后下载对应的 wasm 文件。当然,类似的在线 WebAssembly 工具还有 Mozilla 提供的 WebAssembly Studio。
首先打开 WebAssembly Explorer 页面,然后在左侧粘贴如下 C++ 代码:
int squarer(int num) {
return num * num;
}
正如之前提到的,这是一个非常简单的示例,对于之前没有学习过 C++ 的人也没有任何难度。
下一步就是点击编译(“compile”)按钮,就能看见如下图所示界面,C++ 代码被编译撑了 WAT 格式(WebAssembly text format)的文本。
这里不详述 WAT 格式,展示该格式内容主要是因为相对于 wasm 的二进制格式,这种文本格式更易读。通过 WAT 文件中可以了解 JavaScript 和 WebAssembly 是如何交互的。例如本例中,在 export 关键字后面有 _z7squareri 这个导出的函数名,因为编译器对 C++ 函数名的修饰(mangling)。
这里需要特别注意,因为后面使用 JavaScript 对 C++ 函数进行调用的时候需要依赖这个名字。当然,为了避免这种问题,可以将编译器选择为 C99 或者在函数外层增加 extern "C"块:
extern "C" {
int squarer(int num) {
return num * num;
}
}
这样编译之后函数名称不会有变化。编译成的 WAT 文件内容如下图:
此时导出的函数名和原 C++ 函数中的函数名保持一致。
现在点击下载(“download”)按钮,并将下载的 wasm 文件重命名成 squarer.wasm。
创建一个文件夹,包含刚才下载的 squarer.wasm 文件,并新建下面两个文件:
index.html:包含标准网页的模板。
scripts.js:暂时这是一个空文件,下面就将编写实例化使用的 JavaScript。
目前为止,HTML 标准还不支持将 wasm 文件像 JavaScript 文件那样通过 script 标签直接引入。因此为了加载和实例化 WebAssembly,需要通过 JavaScript 异步的调用 WebAssembly API 来完成这些操作。一共分为三步:
将 wasm 文件加载到数组缓冲区(array buffer)。
将加载的数组编译成 WebAssembly 模块。
实例化 WebAssembly 模块。
实例化之后,JavaScript 就可以直接调用刚才 WAT 文件中 export 的函数和内存了。
最后当然是期待人心的运行了,先来看看 scripts.js 内容:
let squarer;
function loadWebAssembly(fileName) {
return fetch(fileName)
.then(response => response.arrayBuffer())
.then(bits => WebAssembly.compile(bits))
.then(module => { return new WebAssembly.Instance(module) });
};
loadWebAssembly('squarer.wasm')
.then(instance => {
squarer = instance.exports._Z7squareri;
console.log('Finished compiling! Ready when you are...');
});
这里的 loadWebAssembly 函数加载本地的 wasm 文件并进行实例化,最终返回一个 WebAssembly 模块实例。随后从模块中获取导出的函数,随后即可直接调用。这里需要特别注意,导出的函数名和刚才在 WAT 文件中看见的符号需要一致。由于 C++ 编译器对函数名的修饰,建议在对所有需要导出给 JavaScript 的函数,都加上 extern "C"块,避免函数名混乱导致的不匹配。
在 index.html 文件中引入 scripts.js 之后,可以在控制台尝试调用 squarer 函数:
通过这个示例,我们了解了如何将 C++ 代码编译成 WebAssembly 并在浏览器中执行。我们可以将更多的 C、C++、Rust 语言编写的工程放到浏览器中运行,以获得更高的执行效率。当然,还是要再次声明,这里只是一个简单的示例,如果函数的参数不是数字,还会有其他问题。随着 WebAssembly 工具链和集成工具的不断完善,相信编写基于 WebAssembly 的项目一定会更加方便。
https://medium.freecodecamp.org/get-started-with-webassembly-using-only-14-lines-of-javascript-b37b6aaca1e4
「前端之巅」是 InfoQ 旗下关注大前端技术的垂直社群。紧跟时代潮流,共享一线技术,欢迎关注。
PWA、Web 框架、UI 与动画、Node... 大前端的下一站在哪里?前端工程师的价值和成长路径是什么?GMTC2018 上,来自 Google、Facebook、BAT 等 60+ 国内外一线前端大牛,将与你面对面探讨大前端领域最新技术趋势和实践,想要升职加薪就快来吧!扫描下方二维码或点击“阅读原文”了解更多大会详情!
目前大会 8 折热销中,团购更优惠,购票咨询:18514549229(同微信)
以上是关于14行JavaScript教你使用WebAssembly的主要内容,如果未能解决你的问题,请参考以下文章