Hello WebAssembly
在线预览
任务描述
使用 c++写一个 sayHello 方法,并且编译成 Web Assembly,然后在前端调用控制台输出 hello world。
电脑环境安装 (Mac m2 为例)
首先需要有 Emscripten 安装在你的系统上。
Emscripten 是一个能将 C++代码编译为 WebAssembly 的工具。
- 下载 SDK
打开 Emscripten 的官方下载页面并按照页面上的指南进行操作。
# 克隆项目到本地
git clone https://github.com/emscripten-core/emsdk.git
- 配置 SDK
下载完成后,你需要按照提供的说明配置 SDK。
TIP
这里需要 Python3 环境,Mac 电脑默认就有 python3(遇到错误再解决就好了)
# 导航到emsdk目录
cd emsdk
# 安装最新的SDK工具
./emsdk install latest
# 激活最新的SDK工具
./emsdk activate latest
# 配置环境变量
source ./emsdk_env.sh
日志如下:
shaohai.li@192 emsdk % ./emsdk install latest
Resolving SDK alias 'latest' to '3.1.46'
Resolving SDK version '3.1.46' to 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'
Installing SDK 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'..
Skipped installing node-16.20.0-64bit, already installed.
Skipped installing python-3.9.2-64bit, already installed.
Skipped installing releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit, already installed.
All SDK components already installed: 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'.
shaohai.li@192 emsdk % ./emsdk activate latest
Resolving SDK alias 'latest' to '3.1.46'
Resolving SDK version '3.1.46' to 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'
Setting the following tools as active:
node-16.20.0-64bit
python-3.9.2-64bit
releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit
Next steps:
- To conveniently access emsdk tools from the command line,
consider adding the following directories to your PATH:
/Users/shaohai.li/project/emsdk
/Users/shaohai.li/project/emsdk/upstream/emscripten
- This can be done for the current shell by running:
source "/Users/shaohai.li/project/emsdk/emsdk_env.sh"
- Configure emsdk in your shell startup scripts by running:
echo 'source "/Users/shaohai.li/project/emsdk/emsdk_env.sh"' >> $HOME/.zprofile
shaohai.li@192 emsdk %
shaohai.li@192 emsdk % source ./emsdk_env.sh
Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1)
Setting environment variables:
PATH = /Users/shaohai.li/project/emsdk:/Users/shaohai.li/project/emsdk/upstream/emscripten:/Users/shaohai.li/project/ffmpeg:/Library/Frameworks/Python.framework/Versions/2.7/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/shaohai.li/project/phantomjs-2.1.1-macosx/bin
shaohai.li@192 emsdk %
- 测试安装
在完成上述步骤后,可以运行以下命令来测试 Emscripten 是否已成功安装:
emcc -v
如果 Emscripten 已成功安装,这个命令会显示 Emscripten 的版本信息。
正确会输出下面的内容:
shaohai.li@192 emsdk % emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.46 (19607820c447a13fd8d0b7680c56148427d6e1b8)
clang version 18.0.0 (https://github.com/llvm/llvm-project 75501f53624de92aafce2f1da698b249a7293dc7)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/shaohai.li/project/emsdk/upstream/bin
shaohai.li@192 emsdk %
编写 hello.cpp 文件
这段代码导出了一个名为 sayHello
的函数,该函数返回一个字符串“Hello, World!”。
// 引入emscripten/bind.h,这是使用embind时需要的头文件
#include <emscripten/bind.h>
// 使用emscripten命名空间,以简化代码
using namespace emscripten;
// 定义一个名为sayHello的C++函数,它返回一个字符串"Hello, World!"
std::string sayHello() {
return "Hello, World!";
}
// 使用EMSCRIPTEN_BINDINGS宏来创建一个模块。这个模块会将C++的函数、类或变量绑定到JavaScript中。
EMSCRIPTEN_BINDINGS(my_module) {
// 使用function函数将sayHello函数绑定到模块中。在JavaScript中,我们可以通过Module.sayHello()来调用这个C++函数。
function("sayHello", &sayHello);
}
接下来,你可以使用 Emscripten 将 C++文件编译成 WebAssembly 文件。在终端中,进入 C++文件的目录,并执行以下命令:
emcc --bind -o hello.js hello.cpp
运行此命令后,你将在同一目录下获得两个新文件:hello.js
和hello.wasm
。
前端代码
最后,创建一个 HTML 文件来运行 WebAssembly 模块。
创建一个名为 index.html 的文件,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Hello WebAssembly</title>
</head>
<body>
<script src="hello.js"></script>
<!-- 引入通过Emscripten生成的JavaScript文件 -->
<script>
// 当WebAssembly模块准备完毕时执行此函数
Module.onRuntimeInitialized = function () {
// 调用在C++代码中定义的sayHello函数,并在控制台打印返回的字符串
console.log(Module.sayHello()); // 应该在控制台输出: "Hello, World!"
};
</script>
</body>
</html>
这里 Module.onRuntimeInitialized 确保在 WebAssembly 模块准备好之后再调用 sayHello 函数。
本地跑起来
使用 VSCode 安装 live server 插件
点击一下 index.html
使用 Live Server 托管 index.html 启动项目
在你的 VSCode 右下角会有一个 Go Live 按钮,点击它就可以托管 index.html 了