在PHP程序中使用Rust扩展的方法
本文详细介绍如何将Rust代码编译为静态库,并通过C语言桥接封装为PHP扩展。流程涵盖Rust FFI接口定义、C头文件生成、使用ext_skel建立PHP扩展骨架、修改config.m4完成链接,以及解决返回值生命周期引发的段错误问题。
编写Rust静态库与C接口
首先需要编写Rust代码并将其编译为静态库(.a)。关键步骤是使用 #[no_mangle] 保留函数名以便外部调用,并使用 extern "C" 声明ABI兼容性。
// hello_from_rust.rs
#![crate_type = "staticlib"]
extern crate libc;
use std::ffi::CStr;
#[no_mangle]
pub extern "C" fn hello_from_rust(name: *const libc::c_char) {
let buf_name = unsafe { CStr::from_ptr(name).to_bytes() };
let str_name = String::from_utf8(buf_name.to_vec()).unwrap();
println!("Hello from Rust, {}", str_name);
}
使用rustc编译该文件:
rustc --crate-type staticlib hello_from_rust.rs
生成后你会得到一个 libhello_from_rust.a 文件。同时请注意编译器提示需要链接的本地系统库(如 -lSystem -lpthread -lc -lm)。
为C语言创建头文件
为了在C和后续的PHP扩展中调用该函数,需要编写对应的C头文件(hello_from_rust.h):
// hello_from_rust.h
#ifndef __HELLO
#define __HELLO
void hello_from_rust(const char *name);
#endif
构建PHP扩展骨架
PHP提供 ext_skel 脚本用于自动生成扩展基础结构。在PHP源码的 ext/ 目录下运行:
./ext_skel --extname=hello_from_rust
生成的目录结构通常包含 config.m4、hello_from_rust.c、php_hello_from_rust.h 等文件。此时需要将之前生成的 libhello_from_rust.a 和 hello_from_rust.h 复制到该扩展目录中。
配置链接并修改C代码
编辑 config.m4 以指示编译系统如何链接静态库:
PHP_ARG_WITH(hello_from_rust, for hello_from_rust support,
[ --with-hello_from_rust Include hello_from_rust support])
if test "$PHP_HELLO_FROM_RUST" != "no"; then
PHP_SUBST(HELLO_FROM_RUST_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(hello_from_rust, ., HELLO_FROM_RUST_SHARED_LIBADD)
PHP_NEW_EXTENSION(hello_from_rust, hello_from_rust.c, $ext_shared)
fi
在 hello_from_rust.c 中包含头文件并调用函数。注意初始测试版可能因Rust的 println! 或字符串生命周期管理导致段错误(Segfault),建议先确保基础调用通顺。
编译安装与测试
按标准顺序执行编译指令:
$ phpize
$ ./configure --with-hello_from_rust
$ make install
若遇到权限不足可尝试加 sudo。安装成功后可通过命令行验证:
$ php hello_from_rust.php
排错:处理段错误与返回值生命周期
如果在调用过程中出现 Segmentation fault: 11,通常是因为Rust中的临时字符串变量在返回给C时已被销毁。解决方法是调整Rust接口,使其返回由C/C++管理生命周期的指针,或者在C层做好内存拷贝。修正后的Rust签名示例如下:
pub extern "C" fn hello_from_rust(name: *const libc::c_char) -> *const libc::c_char {
// 逻辑... 确保返回指针的有效性或使用CString管理
}
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













