WebAssembly 与 PHP 实战:从入门到精通

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

WebAssembly 与 PHP 简介



WebAssembly (Wasm) 是一种低级的二进制指令格式,在虚拟机中执行,性能接近原生。在 PHP 环境中,它开辟了新的可能性:您可以直接从 PHP 脚本中运行 C、C++、Rust 或 Go 编写的代码,而无需离开服务器环境。这对于资源密集型任务尤其有用——如图像处理、加密、数据解析或数学计算。



在本文中,我们将介绍完整的工作流程:从将源代码编译为 Wasm,到使用 wasmtime 和 wasmer 扩展从 PHP 调用函数。您将了解如何利用机器代码的强大功能来提高 PHP 应用程序的性能。



WebAssembly 基础:PHP 开发者需要了解的内容



Wasm 架构



WebAssembly 在隔离的沙箱中运行。Wasm 模块无法直接访问主机的文件系统、网络或内存——只能访问其线性内存和导出的函数。这确保了安全性,但需要显式地管理数据。



关键概念:

  • 模块 — 编译后的二进制文件 (.wasm)
  • 导出 — 可从外部访问的函数和变量
  • 导入 — 主机 (PHP) 提供给模块的函数
  • 线性内存 — 模块操作的连续字节数组


在 PHP 中使用 Wasm 的工具



有两个主要的扩展:

  • Wasmtime — 来自 Bytecode Alliance,最流行且稳定
  • Wasmer — 替代方案,支持多种后端 (Cranelift, LLVM, Singlepass)


通过 Composer 安装:

composer require wasmtime/wasmtime-php# 或composer require wasmer/wasmer


还需要安装 Wasmtime 或 Wasmer 系统库。对于 Ubuntu:

curl https://wasmtime.dev/install.sh -sSf | bash# 或curl https://get.wasmer.io -sSfL | sh


将 C/C++ 编译为 WebAssembly



使用 Emscripten 进行编译——这是一个基于 LLVM/Clang 的工具集。安装:

git clone https://github.com/emscripten-core/emsdk.gitcd emsdk./emsdk install latest./emsdk activate latestsource ./emsdk_env.sh


示例:C 语言求和函数



创建文件 math.c:

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVEint add(int a, int b) { return a + b;}

EMSCRIPTEN_KEEPALIVEint factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1);}


编译为 Wasm:

emcc math.c -o math.wasm -s WASM=1 -s EXPORTED_FUNCTIONS='["_add","_factorial"]' -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' -O3


标志 -O3 启用最大优化。文件 math.wasm 已准备好使用。



将 Wasm 与 PHP 集成:分步示例



场景 1:使用 Wasmtime



安装扩展并编写以下 PHP 代码:

<?phprequire 'vendor/autoload.php';

use Wasmtime\\Engine;use Wasmtime\\Module;use Wasmtime\\Store;use Wasmtime\\Func;use Wasmtime\\Val;

// 加载模块$engine = new Engine();$module = Module::fromFile($engine, 'math.wasm');$store = new Store($engine);

// 创建实例$instance = new Wasmtime\\Instance($store, $module, []);

// 获取导出的函数$add = $instance->getExport($store, 'add');$factorial = $instance->getExport($store, 'factorial');

// 调用函数$resultAdd = $add->call($store, 5, 7);$resultFact = $factorial->call($store, 10);

echo "5 + 7 = " . $resultAdd[0]->i32() . ""; // 12echo "10! = " . $resultFact[0]->i32()

博客

书籍推荐