Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ jobs:
- { os: ubuntu-26.04, php-version: "8.3", ts: false, debug: false, llvm: "22" }
- { os: ubuntu-26.04, php-version: "8.4", ts: false, debug: false, llvm: "22" }
- { os: ubuntu-26.04, php-version: "8.5", ts: false, debug: false, llvm: "22" }
# Not GA until 2026-11-19. Drop `experimental` then.
- { os: ubuntu-26.04, php-version: "8.6", ts: false, debug: false, llvm: "22", experimental: true }
# Ubuntu - ZTS smoke matrix
- { os: ubuntu-26.04, php-version: "8.5", ts: true, debug: false, llvm: "22" }
# Ubuntu - debug smoke matrix
Expand All @@ -92,8 +94,11 @@ jobs:
- { os: macos-26, php-version: "8.3", ts: false, debug: false }
- { os: macos-26, php-version: "8.4", ts: false, debug: false }
- { os: macos-26, php-version: "8.5", ts: false, debug: false }
# Not GA until 2026-11-19. Drop `experimental` then.
- { os: macos-26, php-version: "8.6", ts: false, debug: false, experimental: true }

runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental == true }}
steps:
- name: Checkout
uses: actions/checkout@v7
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The framework that allows us to write PHP extensions using pure and safe Rust wh
| | macOS | ✅ |
| | Windows | ❌ |
| **PHP Version** | 7.0 ~ 7.4 | ✅ |
| | 8.0 ~ 8.5 | ✅ |
| | 8.0 ~ 8.6 | ✅ |
| **PHP Mode** | NTS | ✅ |
| | ZTS | ✅ |
| **SAPI** | CLI | ✅ |
Expand Down
6 changes: 3 additions & 3 deletions phper/src/arrays.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

//! Apis relate to [zend_array].

use crate::{alloc::EBox, strings::ZStr, sys::*, values::ZVal};
use crate::{alloc::EBox, strings::ZStr, sys::*, utils::ZEND_RESULT_CODE_FAILURE, values::ZVal};
use cfg_if::cfg_if;
use derive_more::From;
use phper_alloc::ToRefOwned;
Expand Down Expand Up @@ -466,7 +466,7 @@ impl<'a> Iterator for RawIter<'a> {

const IS_STRING: u32 = {
cfg_if! {
if #[cfg(all(phper_major_version = "8", phper_minor_version = "5"))] {
if #[cfg(all(phper_major_version = "8", not(any(phper_minor_version = "0", phper_minor_version = "1", phper_minor_version = "2", phper_minor_version = "3", phper_minor_version = "4"))))] {
zend_hash_key_type_HASH_KEY_IS_STRING
} else {
HASH_KEY_IS_STRING
Expand All @@ -476,7 +476,7 @@ impl<'a> Iterator for RawIter<'a> {

const IS_LONG: u32 = {
cfg_if! {
if #[cfg(all(phper_major_version = "8", phper_minor_version = "5"))] {
if #[cfg(all(phper_major_version = "8", not(any(phper_minor_version = "0", phper_minor_version = "1", phper_minor_version = "2", phper_minor_version = "3", phper_minor_version = "4"))))] {
zend_hash_key_type_HASH_KEY_IS_LONG
} else {
HASH_KEY_IS_LONG
Expand Down
2 changes: 1 addition & 1 deletion phper/src/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ pub(crate) unsafe extern "C" fn create_object(ce: *mut zend_class_entry) -> *mut

// Set handlers
let mut handlers = Box::new(std_object_handlers);
handlers.offset = StateObj::<()>::offset() as c_int;
handlers.offset = StateObj::<()>::offset() as _;
handlers.free_obj = Some(free_object);
handlers.clone_obj = has_state_cloner.then_some(clone_object);
(*object).handlers = Box::into_raw(handlers);
Expand Down
34 changes: 31 additions & 3 deletions phper/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
strings::{ZStr, ZString},
sys::*,
types::{ArgumentTypeHint, ReturnTypeHint},
utils::ensure_end_with_zero,
utils::{ZEND_EVAL_CODE, ZEND_USER_FUNCTION, ensure_end_with_zero},
values::{ExecuteData, ZVal},
};
use phper_alloc::ToRefOwned;
Expand Down Expand Up @@ -385,13 +385,13 @@ impl FunctionEntry {

let flags = visibility.unwrap_or(Visibility::default() as u32);

#[allow(clippy::needless_update)]
#[allow(clippy::needless_update, clippy::useless_conversion)]
zend_function_entry {
fname: name.as_ptr().cast(),
handler: raw_handler,
arg_info: Box::into_raw(infos.into_boxed_slice()).cast(),
num_args: arguments.len() as u32,
flags,
flags: flags.into(),
..Default::default()
}
}
Expand Down Expand Up @@ -733,6 +733,34 @@ impl ZFunc {
.map(|o| o.get_mut_class().as_mut_ptr())
.unwrap_or(null_mut());

// PHP 8.6 made `zend_call_known_function` a static inline
// wrapper over `_ex`, which bindgen cannot see.
#[cfg(not(any(
phper_minor_version = "0",
phper_minor_version = "1",
phper_minor_version = "2",
phper_minor_version = "3",
phper_minor_version = "4",
phper_minor_version = "5",
)))]
zend_call_known_function_ex(
function_handler,
object_ptr,
class_ptr,
ret.as_mut_ptr(),
arguments.len() as u32,
arguments.as_mut_ptr().cast(),
null_mut(),
0,
);
#[cfg(any(
phper_minor_version = "0",
phper_minor_version = "1",
phper_minor_version = "2",
phper_minor_version = "3",
phper_minor_version = "4",
phper_minor_version = "5",
))]
zend_call_known_function(
function_handler,
object_ptr,
Expand Down
30 changes: 27 additions & 3 deletions phper/src/ini.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//! Apis relate to [zend_ini_entry_def].

use crate::sys::*;
use cfg_if::cfg_if;
use std::{
ffi::{CStr, c_int},
mem::zeroed,
Expand Down Expand Up @@ -83,6 +84,28 @@ impl IntoIniValue for String {
}
}

cfg_if! {
// `orig` became a `bool` in PHP 8.6.
if #[cfg(any(
phper_major_version = "7",
all(
phper_major_version = "8",
any(
phper_minor_version = "0",
phper_minor_version = "1",
phper_minor_version = "2",
phper_minor_version = "3",
phper_minor_version = "4",
phper_minor_version = "5",
)
)
))] {
const ORIG: i32 = 0;
} else {
const ORIG: bool = false;
}
}

/// The Type which can transform from an ini key name.
///
/// For php7, the zend_ini_* functions receive ini name as `*mut c_char`, but I
Expand All @@ -105,7 +128,7 @@ impl FromIniValue for i64 {
fn from_ini_value(name: &str) -> Self {
unsafe {
let name_ptr = name.as_ptr() as *mut u8 as *mut c_char;
zend_ini_long(name_ptr, name.len().try_into().unwrap(), 0)
zend_ini_long(name_ptr, name.len().try_into().unwrap(), ORIG)
}
}
}
Expand All @@ -115,7 +138,7 @@ impl FromIniValue for f64 {
fn from_ini_value(name: &str) -> Self {
unsafe {
let name_ptr = name.as_ptr() as *mut u8 as *mut c_char;
zend_ini_double(name_ptr, name.len().try_into().unwrap(), 0)
zend_ini_double(name_ptr, name.len().try_into().unwrap(), ORIG)
}
}
}
Expand All @@ -125,7 +148,8 @@ impl FromIniValue for Option<&CStr> {
fn from_ini_value(name: &str) -> Self {
unsafe {
let name_ptr = name.as_ptr() as *mut u8 as *mut c_char;
let ptr = zend_ini_string_ex(name_ptr, name.len().try_into().unwrap(), 0, null_mut());
let ptr =
zend_ini_string_ex(name_ptr, name.len().try_into().unwrap(), ORIG, null_mut());
(!ptr.is_null()).then(|| CStr::from_ptr(ptr))
}
}
Expand Down
2 changes: 1 addition & 1 deletion phper/src/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
ini,
sys::*,
types::Scalar,
utils::ensure_end_with_zero,
utils::{ZEND_RESULT_CODE_SUCCESS, ensure_end_with_zero},
values::ZVal,
};
use std::{
Expand Down
32 changes: 32 additions & 0 deletions phper/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,40 @@

//! Internal useful utils.

use cfg_if::cfg_if;
use std::ffi::CString;

cfg_if! {
if #[cfg(any(
phper_major_version = "7",
all(
phper_major_version = "8",
any(
phper_minor_version = "0",
phper_minor_version = "1",
phper_minor_version = "2",
phper_minor_version = "3",
phper_minor_version = "4",
phper_minor_version = "5",
)
)
))] {
pub(crate) use crate::sys::{
ZEND_EVAL_CODE, ZEND_RESULT_CODE_FAILURE, ZEND_RESULT_CODE_SUCCESS,
ZEND_USER_FUNCTION,
};
} else {
// PHP 8.6 made these C23 enums, so bindgen prefixes them with the
// enum name. Alias them back so call sites read the same everywhere.
use crate::sys::{zend_function_type_ZEND_EVAL_CODE, zend_function_type_ZEND_USER_FUNCTION, zend_result, zend_result_FAILURE, zend_result_SUCCESS};

pub(crate) const ZEND_USER_FUNCTION: u32 = zend_function_type_ZEND_USER_FUNCTION as u32;
pub(crate) const ZEND_EVAL_CODE: u32 = zend_function_type_ZEND_EVAL_CODE as u32;
pub(crate) const ZEND_RESULT_CODE_SUCCESS: zend_result = zend_result_SUCCESS;
pub(crate) const ZEND_RESULT_CODE_FAILURE: zend_result = zend_result_FAILURE;
}
}

pub(crate) fn ensure_end_with_zero(s: impl Into<String>) -> CString {
CString::new(s.into()).expect("CString::new failed")
}
1 change: 1 addition & 0 deletions phper/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
strings::{ZStr, ZString},
sys::*,
types::TypeInfo,
utils::{ZEND_EVAL_CODE, ZEND_USER_FUNCTION},
};
use phper_alloc::RefClone;
use std::{
Expand Down
Loading