正如文章 WebAssembly 开发入门 1:什么是 WebAsssembly 中介绍过的,WebAssembly 语言本身类似于汇编语言,不太适合用来编程。如果要使用 WebAssembly 进行开发通常是使用 C/C++ 这些主流语言开发,然后使用 emsdk 中提供的工具编译为 WebAssembly 代码供 JavaScript 来调用。
本文来看一下如何使用 C 语言开发,并将 C 语言函数编译导出为 WebAssembly 函数供 JavaScript 调用。
// filename: mathmodule.c
#include <emscripten.h>
// 加法
EMSCRIPTEN_KEEPALIVE int add(int a, int b){
return a + b;
}
// 减法
EMSCRIPTEN_KEEPALIVE int subtract(int a, int b){
return a - b;
}
// 乘法
EMSCRIPTEN_KEEPALIVE int multiply(int a, int b){
return a * b;
}
// 除法
EMSCRIPTEN_KEEPALIVE int divide(int a, int b){
return a / b;
} 上面是一个 C 语言源文件 (mathmodule.c),其中定义了 4 个导出函数,头文件 emscripten.h 中定义了用于到导出 WebAssembly 函数的宏 EMSCRIPTEN_KEEPALIVE。
打开 PowerShell 控制台,将 mathmodule.c 编译为 WebAssembly 文件 (.js 和 .wasm) 的命令为:
# 激活 EMSDK 环境
${Env:EMSDK}/emsdk_env.bat
# 编译 WebAssembly
emcc mathmodule.c -o mathmodule.js \
-O3 \
-s EXPORTED_RUNTIME_METHODS="['ccall','cwrap']" \
-s EXPORTED_FUNCTIONS="['_malloc','_free']" \
-s EXPORT_NAME='MathModule' \
-s MODULARIZE=1 环境变量 EMSDK 是 emsdk 的安装目录,emsdk 的安装配置可以参考WebAssembly 开发入门 2:安装配置开发环境。emcc 是 emsdk 中提供的用于将 C/C++ 代码编译为 WebAssembly 代码的命令,命令运行成功之后,当前目录会多出两个文件 mathmodule.js 和 mathmodule.wasm。
emcc 运行时加了一些参数参数,-O3 是优化参数,-s EXPORTED_RUNTIME_METHODS 定义了要导出的运行时方法名称,-s EXPORTED_FUNCTIONS 定义了要导出的函数名称(C 代码中用 EMSCRIPTEN_KEEPALIVE 修饰的函数会自动导出,无需在此列出),-s EXPORT_NAME 定义了生成的 WebAssembly 模块的名称,-s MODULARIZE=1 表示要生成模块。emcc 命令还有很多其他的参数,具体可以参考官方文档:https://emscripten.org/docs/tools_reference/emcc.html。
要测试生成的 .js 和 .wasm 文件,需要编写一个网页。在当前目录中新建一个 index.html 文件,文件内容为:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Wasm测试</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.result { background: #f4f4f4; padding: 15px; border-radius: 5px; margin-top: 10px; }
</style>
</head>
<body>
<h1>WebAssembly 测试</h1>
<button onclick="runTest()">开始运行测试</button>
<div id="output" class="result">点击按钮开始测试 add(1, 2)</div>
<script src="./mathmodule.js"></script>
<script>
async function runTest() {
const mathModule = await MathModule();// 初始化 Emscripten 模块
const result = mathModule._add(1, 2);
output.innerHTML = `
<h3>Compute Result:</h3>
<p>${result.toFixed(4)}</p>
`;
}
</script>
</body>
</html> 在 mathmodule.js 定义了一个函数 MathModule,调用这个函数可以创建一个 WebAssembly 模块,其中就有在 C 语言中定义的 4 个导出函数 (add、subtract、multiply、divide)。这些导出函数都成了模块的成员(名称前多了一个下划线,例如:C 语言函数 add 导出到 WebAssembly 模块中的名称为 _add),可以直接在 JavaScript 代码中调用。
需要注意的是,出于安全方面的原因,浏览器打开的本地网页文件上无法运行 WebAssembly 代码。需要为 index.html 网页创建一个 Web 服务器,然后通过这个 web 服务器的 IP:PORT 来访问这个页面才能运行其中的 WebAssembly 代码。一个比较简单的创建 Web 服务器方法是使用 Python 的 http.server 模块。在 index.html 文件所有目录打开一个控制台,运行命令:
$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 从浏览器打开网址 http://127.0.0.1:8000 就可以打开 index.html 页面。点击页面中的按钮调用 _add 函数,得到使用 WebAssembly 代码运行得到的计算结果。
#WebAssembly# #Wasm# #C# #emcc# #emsdk##javascript# #Web开发#
(完)