发表于: 2019-12-22 13:34:13
1 1246
今日完成:
WebAssembly的使用
介绍
WebAssembly(缩写为Wasm)是基于堆栈的虚拟机的二进制指令格式。Wasm被设计为可移植目标,用于编译高级语言(如C / C ++ / Rust),从而可以在Web上为客户端和服务器应用程序进行部署。
安装环境
在windows环境下构建WebAssembly的工具链Emscripten
在开始构建安装之前,你需要确保你本地已经安装好了以下的工具:
- Git
- CMake
- Python 2.7.x
一切准备就绪后,就可以通过Emscripten SDK来构建Emscripten了。步骤如下:
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
git pull
./emsdk install latest
./emsdk activate latest
emsdk_env.bat
其中最关键的是第四步,也是比较耗时的一步,耐心等待吧。
安装好了之后,需要注意的是每次重新打开命令行控制台后,都需要进行第5、6步骤,
才能正常使用Emscripten工具来编译。可以通过命令emcc -v
来检测。结果如下则表示安装成功可以正常使用:
PS D:\webAssemblyDemo\emsdk> emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.39.4
clang version 10.0.0 (Cswircachegitchromium.googlesource.com-external-github.com-llvm-llvm--project b5f295ffcec2fa7402e39eb1262acbd55a7d39f5)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: D:/webAssemblyDemo/emsdk/upstream/bin
shared:INFO: (Emscripten: Running sanity checks)
可以看到emcc版本为1.39.4 ,一般按照上面步骤正常操作的话版本都没有问题,但如果你的版本在1.37或更低,那你就需要注意了:
emcc 在 1.37 以上版本才支持直接生成 wasm 文件。
开始一个简单的Demo
参考官方给出的demo来进行WebAssembly的初试:编写一个简单的C程序,使用emcc命令将其进行编译,最后在浏览器中运行。
• 在使用emcc命令时,要带着 -s WASM=1参数(不然,默认会编译成asm.js)
• 如果我们想让Emscripten生成一个我们所写程序的HTML页面,并带有wasm和JavaScript文件,我们需要给输出的文件名加.html后缀名。
• 最后,当我们运行程序的时候,我们不能直接在浏览器中打开HTML文件,因为跨域请求是不支持file协议的,我们需要将我们的文件输出在http协议上。
demo步骤如下:
编写C程序文件jnshu.c如下:
#include<stdio.h> int main(int argc,char ** argv){ printf("www.jnshu.com"); }
使用命令
emcc jnshu.c -s WASM=1 -o jnshu.html
编译文件
编译后会生成 jnshu.html、 jnshu.wasm、 jnshu.js三个文件
使用emrum命令来创建一个http协议的web server来展示编译后的文件
emrun --no_browser --port 8080 .\jnshu.html
通过浏览器来访问
可以看到C程序打印的官网地址已经成功的在控制台上展示。
通过javascript来调用wasm文件
重新写一个C程序:
#include<stdio.h>
int square(int x){
return x * x;
}
int add (int x, int y){
return x + x;
}
这次的程序中没有main函数,只有两个方法。接下来使用emcc命令将其编译为wasm文件,并在js中调用它。
使用下面的命令直接将c编译为wasm文件:emcc .\last.c -Os -s WASM=1 -s SIDE_MODULE=1 -o last.wasm
以十六进制编码的方式打开查看这个二进制文件:
它的开头几位为 20 61 73 6D,这个是判断一个文件是否符合wasm格式的标准。
它对应的ASCII码为: asm
之前说了emcc 在 1.37 以上版本才支持直接生成 wasm 文件
。低版本通过命令貌似也可以生成一个后缀为.wasm的文件,编译过程不会报错。但在浏览器中调用wasm文件时就会报出wasm文件首部编码不匹配的问题。
有了wasm文件后,就可以在js中调用它了。
下面给出加载wasm模块的方法,这也是官方目前最为推荐的一种方式。
使用fetchAndInstantiate方法来获取WebAssembly模块,并将其实例化:
function fetchAndInstantiate(url, importObject={}) {
return fetch(url).then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results =>
results.instance
);
}
js得到wasm实例后,就可以使用webAssembly.Instance.exports导出的方法了。
fetchAndInstantiate('math.wasm').then(function(instance) {
//调用导出的函数
var add = instance.exports.add
var square = instance.exports.square
console.log('1+1=',add(1,1))
console.log('2*2=',square(2))
})
math.wasm需要与math.js在同一路径下。
最后将这段js代码加入math.html中,并通过htttp来访问:
如果你的浏览器是Firefox 54+的话,
其Developer Tool Debugger Panel模式可以将网页中包含的任何 wasm 代码转换为文本格式(wat),如下:
(export "add" $func1),(export "square" $func1)可以看到C程序中的两个方法被导出为add,square。这个很关键。看了很多教程,大家在使用如上方法调用wasm模块时,默认给方法名前加_,
如:var add = instance.exports._add。在低版本好像是这样的,导致我在升级版本后,调用模块总是提示没有此方法。查看了wasm的文本后才明白,新版直接调用方法名就可以了。
文章中所有的代码已整理放入github仓库:
https://github.com/zln312/webassembly_demo.git
参考文档:
https://webassembly.org/getting-started/developers-guide/
https://emscripten.org/docs/getting_started/downloads.html
明日计划:
继续js任务
学习微信小程序
收获:
发现了一款比较好用的笔记记录软件Joplin
简单了解了下markdown的使用,排版非常方便
遇到的问题:
最近总是熬夜,效率太低了。
以后不能再这样了,管理好时间。
评论