Phper:使用纯正且安全的 Rust 语言编写 PHP 扩展

编写你的第一个扩展
在这里,我们将编写一个 “Hello World” 扩展,它包含一个函数,接收人名并向此人输出问候语。
完整示例请访问:https://github.com/phper - framework/phper/tree/master/examples/hello 。
步骤
- 确保安装了libclang(bindgen所需)
phper require libclang 9.0+
- 如果你使用的是类似Debian的Linux系统:
sudo apt install llvm - 10 - dev libclang - 10 - dev
- 创建Cargo项目,并指定扩展名称
cargo new --lib hello
cd hello
- 在Cargo.toml中添加元数据以构建.so文件
- Cargo.toml
[lib]
crate - type = ["cdylib"]
- 运行命令添加phper依赖
cargo add phper
- 创建build.rs(适配MacOS)
fn main() {
#[cfg(target_os = "macos")]
{
println!("cargo:rustc - link - arg=-undefined");
println!("cargo:rustc - link - arg=dynamic_lookup");
}
}
- 将以下代码添加到src/lib.rs
use phper::{echo, functions::Argument, modules::Module, php_get_module, values::ZVal};
/// 这个PHP函数接收类型为`ZVal`的参数。
fn say_hello(arguments: &mut [ZVal]) -> phper::Result<()> {
// 获取第一个参数,期望类型为`ZStr`,并转换为Rust的UTF - 8字符串。
let name = arguments[0].expect_z_str()?.to_str()?;
// 此宏用于执行PHP内部的`echo`操作。
echo!("Hello, {}!\n", name);
Ok(())
}
/// 这是PHP扩展的入口,`php_get_module`属性宏将生成`extern "C" fn`。
#[php_get_module]
pub fn get_module() -> Module {
// 使用扩展信息新建`Module`。
let mut module = Module::new(
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
env!("CARGO_PKG_AUTHORS"),
);
// 注册函数`say_hello`,该函数有一个参数`name`。
module.add_function("say_hello", say_hello).argument(Argument::by_val("name"));
module
}
- 构建:如果你的PHP没有全局安装,你应该指定php - config的路径。
- 可选,若PHP未全局安装则指定路径:此环境变量由
phper - sys
使用。 export PHP_CONFIG=<你的php - config路径>
- 构建libhello.so:
cargo build
- 可选,若PHP未全局安装则指定路径:此环境变量由
- 使用扩展运行PHP命令
php -d "extension = target/debug/libhello.so" -r "say_hello('Bob');"
然后你会得到输出:
Hello, Bob!
Publish on 2025-01-08,Update on 2025-02-10