#php #api-bindings #zend

ext-php-rs

为构建原生Rust PHP扩展而设计的Zend API绑定

35个版本

0.12.0 2024年1月26日
0.11.2 2023年11月28日
0.10.5 2023年11月24日
0.10.1 2023年5月16日
0.0.7 2021年5月21日

25FFI

Download history 234/week @ 2024-04-27 108/week @ 2024-05-04 341/week @ 2024-05-11 423/week @ 2024-05-18 259/week @ 2024-05-25 410/week @ 2024-06-01 432/week @ 2024-06-08 604/week @ 2024-06-15 244/week @ 2024-06-22 140/week @ 2024-06-29 307/week @ 2024-07-06 683/week @ 2024-07-13 197/week @ 2024-07-20 164/week @ 2024-07-27 171/week @ 2024-08-03 444/week @ 2024-08-10

1,020 每月下载量
5 crates 中使用

MIT/Apache

500KB
10K SLoC

ext-php-rs

Crates.io docs.rs Guide Workflow Status CI Workflow Status Discord

用于在Rust中构建PHP扩展的Zend API绑定和抽象。

示例

导出简单的函数 function hello_world(string $name): string 到PHP

#![cfg_attr(windows, feature(abi_vectorcall))]

use ext_php_rs::prelude::*;

/// Gives you a nice greeting!
/// 
/// @param string $name Your name.
/// 
/// @return string Nice greeting!
#[php_function]
pub fn hello_world(name: String) -> String {
    format!("Hello, {}!", name)
}

// Required to register the extension with PHP.
#[php_module]
pub fn module(module: ModuleBuilder) -> ModuleBuilder {
    module
}

使用 cargo-php 构建IDE存根并安装扩展

$ cargo install cargo-php
  Installing cargo-php v0.1.0
$ cargo php stubs --stdout
  Compiling example-ext v0.1.0
  Finished dev [unoptimized + debuginfo] target(s) in 3.57s
<?php

// Stubs for example-ext

/**
 * Gives you a nice greeting!
 *
 * @param string $name Your name.
 *
 * @return string Nice greeting!
 */
function hello_world(string $name): string {}
$ cargo php install --release
  Compiling example-ext v0.1.0
  Finished release [optimized] target(s) in 1.68s
Are you sure you want to install the extension `example-ext`? yes
$ php -m
[PHP Modules]
// ...
example-ext
// ...

从PHP调用函数

var_dump(hello_world("David")); // string(13) "Hello, David!"

更多示例,请参阅库 指南

特性

  • 易于使用: 内置宏可以抽象掉与Zend API交互的需求,例如Rust类型函数参数可以抽象掉与Zend值的交互。
  • 轻量级: 您不必使用内置的帮助宏。您可以为自己的函数编写自己的粘合代码。
  • 可扩展: 为您的自定义类型实现 IntoZvalFromZval,允许该类型作为函数参数和返回类型使用。

目标

我们的主要目标是 使扩展开发更容易。

  • 用C编写扩展可能是乏味的,而Zend API有限的文档可能会让人感到 intimidating。
  • Rust的现代语言功能和功能丰富的标准库是C的重大改进。
  • 抽象掉原始的Zend API可以让扩展开发更快,更有信心。
  • 抽象化还允许我们在不显著修改扩展代码的情况下支持 PHP 的未来(以及可能的过去)版本。

文档

库指南可以在这里阅读:https://davidcole1340.github.io/ext-php-rs.

项目采用内联文档,因此查看 cargo 文档是目前最好的资源。这可以在 docs.rs 上查看。

要求

  • 基于 Linux、macOS 或 Windows 的操作系统。
  • PHP 8.0 或更高版本。
    • 不计划支持 PHP 的早期版本。
  • Rust。
    • 目前,我们不做 MSRV 的保证,然而在撰写时,lib.rs 建议使用 Rust 1.57。
  • Clang 5.0 或更高版本。

Windows 要求

  • 扩展只能为从 https://windows.php.net 获取的 PHP 安装编译。最终计划支持其他安装。
  • Windows 需要 Rust nightly。这是由于一些 PHP 函数在 Windows 上使用 vectorcall 调用约定,而 Rust 中的这个调用约定仅作为 nightly 不稳定功能提供。
  • 建议使用 rust-lld 链接器来链接您的扩展。MSVC 链接器(link.exe)受支持,但如果链接器版本不受您的 PHP 安装支持,您可能会遇到问题。您可以通过创建一个包含以下内容的 .cargo\config.toml 文件来使用 rust-lld 链接器:
    # Replace target triple if you have a different architecture than x86_64
    [target.x86_64-pc-windows-msvc]
    linker = "rust-lld"
    
  • cc 仓库需要系统上存在 cl.exe。这通常与 Microsoft Visual Studio 一起捆绑。
  • cargo-php 的存根生成功能在 Windows 上不可用。将此功能重写为跨平台功能正在计划中。

Cargo 功能

默认情况下,所有功能都被禁用。

  • closure - 允许将 Rust 闭包返回给 PHP。创建一个新的类类型,RustClosure
  • anyhow - 为 anyhow::Error 实现 Into<PhpException>,允许您从 PHP 函数中返回 anyhow 结果。支持 anyhow v1.x。

用法

检查以下示例项目之一

  • anonaddy-sequoia - Sequoia 加密 PHP 扩展。
  • opus-php - PHP 中 Opus 编码器的音频编码器。
  • tomlrs-php - TOML 数据格式解析器。
  • php-scrypt - scrypt 密码散列算法的 PHP 包装器。
  • fluent-php - Mozilla 项目 Fluent i18n 库的 PHP 包装器。

贡献

非常欢迎贡献。我是一个 Rust 开发新手,任何建议都欢迎。请通过 Github 提交问题和 PR。

欢迎的贡献包括

  • 文档扩展(尤其是示例!)
  • 安全性审查(特别是如果您有 Rust 和 Zend API 的经验)。
  • 错误修复和功能。
  • 功能请求。

除非您明确说明,否则任何有意提交以包含在您的工作中的贡献,如 Apache-2.0 许可证中定义的,将按照上述方式双许可,不附加任何其他条款或条件。

资源

许可证

根据以下任一许可进行许可:

由您选择。

依赖项

~2-10MB
~114K SLoC