WebAssembly 开发入门 3:使用 C 语言开发
计算学徒
编辑于 2026年01月26日 20:45
收录于文集
共106篇
web前端学习

正如文章 WebAssembly 开发入门 1:什么是 WebAsssembly​ 中介绍过的,WebAssembly 语言本身类似于汇编语言,不太适合用来编程。如果要使用 WebAssembly 进行开发通常是使用 C/C++ 这些主流语言开发,然后使用 emsdk 中提供的工具编译为 WebAssembly 代码供 JavaScript 来调用。

本文来看一下如何使用 C 语言开发,并将 C 语言函数编译导出为 WebAssembly 函数供 JavaScript 调用。

代码块
C
自动换行
复制代码
// 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) 的命令为:

代码块
Shell
自动换行
复制代码
# 激活 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 文件,文件内容为:

代码块
XML
自动换行
复制代码
<!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 文件所有目录打开一个控制台,运行命令:

代码块
Shell
自动换行
复制代码
$ 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开发#​

(完)