使用WebAssembly和PHP:高级水平

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

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

开始课程

引言:为什么在PHP中使用WebAssembly?

在Web开发世界中,PHP仍然是服务器端最流行的语言之一。然而,当涉及到高性能计算——图像处理、复杂数学运算、即时编译代码或使用C/C++/Rust代码时——原生PHP往往力不从心。正是在这里,WebAssembly (WASM) 派上了用场。

WebAssembly是一种二进制指令格式,以接近原生的速度执行。传统上,它与浏览器相关联,但现代运行时(Wasmer、Wasmtime)允许在服务器上运行WASM模块,包括从PHP中运行。在本文中,我们将探讨将WebAssembly集成到PHP应用程序中的高级技术:从环境设置到创建复杂模块和性能优化。



1. 环境设置:Wasmer和PHP扩展

为了在PHP中使用WebAssembly,我们需要一个特殊的扩展。最成熟且有文档记录的选项是 wasmer-php。

安装Wasmer

首先,安装Wasmer运行时本身:

curl https://get.wasmer.io -sSfL | sh# 或者通过包管理器 (macOS/Linux)brew install wasmer

安装PHP扩展

可以通过PECL安装扩展,或者手动编译:

# 通过PECLsudo pecl install wasmer

# 或者从源码编译(适用于高级用户)git clone https://github.com/wasmerio/wasmer-php.gitcd wasmer-phpphpize./configuremakesudo make install

安装后,将 extension=wasmer.so 添加到您的 php.ini 文件中,然后重启服务器。检查是否正常工作:

<?phpecho class_exists('\\\\Wasmer\\\\Instance') ? 'WASM Ready' : 'Not installed';?>


2. 从PHP加载和执行WASM模块

假设我们有一个编译好的模块 math.wasm,它导出了一个函数 add(a, b)(用Rust或C编写)。让我们加载它并从PHP调用它。

基本示例:调用函数

<?phpuse Wasmer\\Instance;use Wasmer\\Module;use Wasmer\\Memory;use Wasmer\\Value;

// 1. 加载模块$wasm_bytes = file_get_contents(__DIR__ . '/math.wasm');$module = new Module($wasm_bytes);

// 2. 创建实例$instance = new Instance($module);

// 3. 获取导出的函数$add = $instance->exports->get('add');

// 4. 使用参数调用$result = $add(5, 7);

echo "结果: " . $result->toInt(); // 输出: 12?>

重要提示:WASM函数处理简单类型(i32、i64、f32、f64)。对于复杂结构(字符串、数组),需要通过线性内存(Memory)进行传递。



内存操作:传递字符串

如果您的WASM模块期望一个字符串,您需要将其写入共享内存并传递指针:

<?php// 假设WASM函数 'greet' 接受一个指向字符串的指针 (i32)$memory = $instance->exports->get('memory');$greet = $instance->exports->get('greet');

// 将字符串写入内存(以空字节结尾)$input = "Hello from PHP!";$ptr = 100; // 任意地址,必须空闲$memory->write($ptr, $input . "\\0");

// 调用函数$result_ptr = $greet($ptr);

// 从内存中读取结果$output = '';$offset = $result_ptr->toInt();while (($byte = $memory->read($offset, 1)) !== "\\0") { $output .= $byte; $offset++;}echo $output; // 来自WASM的问候?>


3. 构建您自己的WASM模块 (Rust → PHP)

为了获得最大性能,通常使用Rust。让我们看一个最小的例子。

Rust代码

创建一个新项目:

cargo new --lib wasm_mathcd wasm_math

文件 Cargo.toml:

[lib]crate-type = ["cdylib"]

[depend

博客

书籍推荐