From da694300b89d1df87961161e03af33f66402a5bd Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers <7943856+bschoenmaeckers@users.noreply.github.com> Date: Thu, 17 Sep 2026 14:09:16 +0200 Subject: [PATCH] Add `Py_IncRef`, `Py_DecRef`, `Py_XNewRef` (#8726) --- crates/capi/src/refcount.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/capi/src/refcount.rs b/crates/capi/src/refcount.rs index 48c7132b0..9979bf4ab 100644 --- a/crates/capi/src/refcount.rs +++ b/crates/capi/src/refcount.rs @@ -2,12 +2,26 @@ use crate::{PyObject, pystate::with_vm}; use core::ptr::NonNull; use rustpython_vm::PyObjectRef; +#[unsafe(no_mangle)] +pub unsafe extern "C" fn Py_DecRef(op: *mut PyObject) { + if !op.is_null() { + unsafe { _Py_DecRef(op) } + } +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn _Py_DecRef(op: *mut PyObject) { // By dropping PyObjectRef, we will decrement the reference count. unsafe { drop(PyObjectRef::from_raw(NonNull::new_unchecked(op))) }; } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn Py_IncRef(op: *mut PyObject) { + if !op.is_null() { + unsafe { _Py_IncRef(op) } + } +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn _Py_IncRef(op: *mut PyObject) { // Don't drop the owned value, as we just want to increment the refcount. @@ -19,6 +33,15 @@ pub unsafe extern "C" fn Py_NewRef(op: *mut PyObject) -> *mut PyObject { with_vm(|_vm| unsafe { (*op).to_owned() }) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn Py_XNewRef(op: *mut PyObject) -> *mut PyObject { + if op.is_null() { + core::ptr::null_mut() + } else { + unsafe { Py_NewRef(op) } + } +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn Py_REFCNT(op: *mut PyObject) -> isize { with_vm(|_vm| unsafe { &*op }.strong_count()) @@ -45,4 +68,12 @@ mod tests { assert_eq!(ffi::Py_REFCNT(obj.as_ptr()), ref_count); }); } + + #[test] + fn incdec_null_is_noop() { + unsafe { + ffi::Py_IncRef(core::ptr::null_mut()); + ffi::Py_DecRef(core::ptr::null_mut()); + } + } }