WebAssembly和Emscripten入门简介

用户头像
北京/UI设计师/2年前/337浏览
WebAssembly和Emscripten入门简介

通过不断的学习WebAssembly开发技术,可以帮助开发人员在Web平台上构建更快、更安全、更可移植的应用程序。

01

初识WebAssembly

WebAssembly,简称 WASM ,是一种新的低级二进制格式,它可以在所有主流的浏览器中使用,包括 Chrome,Firefox,Edge和Safari。WebAssembly最初由Mozilla、Google、微软和其他技术公司推出,它的目标是通过提供一种高性能、可移植和安全的方式来扩展Web平台,以便开发人员可以在Web上构建更加复杂和功能更加强大的应用程序。


WebAssembly与JavaScript不同,它是一种二进制格式,而不是文本格式,它需要使用虚拟机来解释字节码,同时提供与Web技术的交互。WebAssembly可以将C/C++、Rust等语言编写的代码编译成字节码格式,然后在浏览器中运行。WebAssembly可以通过使用JavaScript的API调用,也可以在WebAssembly模块之间进行通信。WebAssembly可以更快地加载、解析和执行,从而提供更好的性能和更低的内存占用。


02

Emscripten开发入门

WebAssembly需要将C/C++、Rust等语言编写的代码编译成字节码格式,然后在浏览器中运行。Emscripten是一个将C/C++代码转换为WebAssembly的工具集,是WebAssembly技术的重要推动者之一。Emscripten的核心是一个将LLVM字节码转换为JavaScript或WebAssembly字节码的编译器,称为LLVM到JavaScript的编译器。该编译器可以将C/C++代码编译为LLVM字节码,然后通过LLVM到JavaScript编译器将字节码转换为JavaScript或WebAssembly代码。通过利用Emscripten工具,开发者可以使用C/C++等语言来开发Web应用,利用WebAssembly的高性能、低资源消耗、跨平台等优势来提升Web应用的性能和用户体验。


使用Emscripten开发编译流程大致如下:


#01

Emscripten安装

安装Emscripten需要使用emsdk脚本,emsdk脚本是基于python语言开发的,安装前需要确认有以下依赖项:`git`,`python`,`Node.js`。


安装步骤如下:

在终端中输入以下命令

git clone https://github.com/emscripten-core/emsdk.git

cd emsdk

git pull

./emsdk install latest

./emsdk activate latest


配置环境变量

source ./emsdk_env.sh

安装完成后的目录

安装结束后进行版本校验,查看版本信息

emcc -v


#02

Hello, Emscripten

接下来我们开始Emscripten开始之旅,新建一个`hello.cpp`文件,代码如下:

// hello.cpp


#include


using namespace std;


int main() {

cout << "Hello, World!" << endl;

return 0;

}


切换到当前工程目录,在控制台使用`emcc`命令生成wasm文件,通过`-o`选项指定输出文件:

emcc hello.cpp -o hello.js


编译完成后在目录中会生成`hello.js`文件和`hello.wasm`文件。

被编译成WebAssembly后的C/C++代码是不能直接运行的,需要通过浏览器加载运行。

在同一个目录,我们继续新建一个`hello.html`文件,并引入`hello.js`文件:

在浏览器中打开`hello.html`文件,在开发者面板中的Console中能够看到`hello.cpp`的输出内容。

WebAssembly是一种跨平台的字节码,不仅可以在浏览器中运行,也可以在node环境中运行:


#03

WebAssembly和JavaScript交互

如果要实现一个实用功能的WebAssembly模块,必然需要提供能够和外部交互的函数接口。包括JavaScript调用C/C++函数功能,C/C++函数调用JavaScript方法,以及C/C++函数和JavaScript交换数据等需求。


Emscripten编译生成的js文件是一种胶水代码,用来加载WebAssembly模块和导出相关函数。生成的js代码中有一个全局对象Module,该全局对象是Emscripten的核心,负责WebAssembly模块的载入、创建初始化等,以及对C/C++函数进行封装等功能。在之前`hello.js`中有对`hello.cpp`中的`main`函数的封装代码如下:

Emscripten会对封装导出的函数前面加上下划线,`main()`函数会被封装成`_main()`。我们可以在浏览器控制台中直接使用`_main()`函数。


#04

JavaScript调用C/C++函数

接下来我们新建一个export.cpp文件,代码如下:

我们定义了一个`EM_PORT_API`的宏定义,用来统一C和C++环境,方便用来导出函数。其中`__EMSCRIPTEN__`是用来识别Emscripten环境,`__cplusplus`是用来判断C++代码,`EMSCRIPTEN_KEEPALIVE`是Emscripten的宏定义,用来优化编译的。

切换到工程目录,在控制台使用emcc命令生成wasm文件:

目录中生成文件:`export.js`和`export.wasm`。继续在浏览器中测试我们的代码,新建一个`export.html`文件,代码如下:

WebAssembly实例是通过方法createWasm()异步创建的,有可能js文件加载后,Emscripten运行环境没有准备好,我们需要通过建立一种Emscripten运行时准备就绪的机制。一种简单的方法就是使用onRuntimeInitialized回调方法,在这个回调方法中运行WebAssembly Module导出的方法。

通过运行浏览器,我们可以在控制台查看JavaScript调用C++代码的结果:


#05

C/C++函数调用JavaScript方法

反过来,我们也可以在C/C++函数调用JavaScript方法。首先需要创建一个`call_js.cpp`文件,代码如下:

我们在`call_js.cpp`文件中声明了`js_add`和`js_console_log`两个函数,这两个函数/方法的具体实现是在js文件中。接着新建一个`mylibrary.js`文件,代码如下:

按照在C++文件中声明的方法签名,在js文件中实现了`js_add`和`js_console_log`的方法功能,并合并注入到`LibraryManager.library`中。`LibraryManager.library`对象可以简单理解为是JavaScript注入到C/C++中的运行时库。

在控制台使用emcc命令生成wasm文件,需要使用`--js-library`链接外部的js文件:

继续新建一个`call_js.html`文件用来测试代码,在浏览器查看我们的运行结果。

浏览器的运行结果如下:


03

总结

我们简单的展示了C/C++和JavaScript函数之间通过WebAssembly的相互调用,在这里并没有涉及到复杂的数据交换和相关的内存模型操作。WebAssembly是一个强大的Web应用技术,可以为Web应用程序提供更好的性能和更多强大的功能。Emscripten是一个用来开发WebAssembly应用的强大工具集。通过不断的学习WebAssembly开发技术,可以帮助开发人员在Web平台上构建更快、更安全、更可移植的应用程序。



1
Report
|
1
Share
相关推荐
评论
用户头像
in to comment
Add emoji
喜欢TA的作品吗?喜欢就快来夸夸TA吧!
推荐素材
You may like
相关收藏夹
大家都在看
Log in