pyo3_ffi/
object.rs

1use crate::pyport::{Py_hash_t, Py_ssize_t};
2#[cfg(Py_GIL_DISABLED)]
3use crate::PyMutex;
4#[cfg(Py_GIL_DISABLED)]
5use std::marker::PhantomPinned;
6use std::mem;
7use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void};
8use std::ptr;
9#[cfg(Py_GIL_DISABLED)]
10use std::sync::atomic::{AtomicIsize, AtomicU32, AtomicU8, Ordering::Relaxed};
11
12#[cfg(Py_LIMITED_API)]
13opaque_struct!(PyTypeObject);
14
15#[cfg(not(Py_LIMITED_API))]
16pub use crate::cpython::object::PyTypeObject;
17
18#[cfg(Py_3_12)]
19const _Py_IMMORTAL_REFCNT: Py_ssize_t = {
20    if cfg!(target_pointer_width = "64") {
21        c_uint::MAX as Py_ssize_t
22    } else {
23        // for 32-bit systems, use the lower 30 bits (see comment in CPython's object.h)
24        (c_uint::MAX >> 2) as Py_ssize_t
25    }
26};
27
28#[cfg(Py_GIL_DISABLED)]
29const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
30
31#[allow(clippy::declare_interior_mutable_const)]
32pub const PyObject_HEAD_INIT: PyObject = PyObject {
33    #[cfg(py_sys_config = "Py_TRACE_REFS")]
34    _ob_next: std::ptr::null_mut(),
35    #[cfg(py_sys_config = "Py_TRACE_REFS")]
36    _ob_prev: std::ptr::null_mut(),
37    #[cfg(Py_GIL_DISABLED)]
38    ob_tid: 0,
39    #[cfg(Py_GIL_DISABLED)]
40    _padding: 0,
41    #[cfg(Py_GIL_DISABLED)]
42    ob_mutex: PyMutex {
43        _bits: AtomicU8::new(0),
44        _pin: PhantomPinned,
45    },
46    #[cfg(Py_GIL_DISABLED)]
47    ob_gc_bits: 0,
48    #[cfg(Py_GIL_DISABLED)]
49    ob_ref_local: AtomicU32::new(_Py_IMMORTAL_REFCNT_LOCAL),
50    #[cfg(Py_GIL_DISABLED)]
51    ob_ref_shared: AtomicIsize::new(0),
52    #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
53    ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 },
54    #[cfg(not(Py_3_12))]
55    ob_refcnt: 1,
56    #[cfg(PyPy)]
57    ob_pypy_link: 0,
58    ob_type: std::ptr::null_mut(),
59};
60
61// skipped PyObject_VAR_HEAD
62// skipped Py_INVALID_SIZE
63
64// skipped private _Py_UNOWNED_TID
65
66#[cfg(Py_GIL_DISABLED)]
67const _Py_REF_SHARED_SHIFT: isize = 2;
68// skipped private _Py_REF_SHARED_FLAG_MASK
69
70// skipped private _Py_REF_SHARED_INIT
71// skipped private _Py_REF_MAYBE_WEAKREF
72// skipped private _Py_REF_QUEUED
73// skipped private _Py_REF_MERGED
74
75// skipped private _Py_REF_SHARED
76
77#[repr(C)]
78#[derive(Copy, Clone)]
79#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
80/// This union is anonymous in CPython, so the name was given by PyO3 because
81/// Rust unions need a name.
82pub union PyObjectObRefcnt {
83    pub ob_refcnt: Py_ssize_t,
84    #[cfg(target_pointer_width = "64")]
85    pub ob_refcnt_split: [crate::PY_UINT32_T; 2],
86}
87
88#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
89impl std::fmt::Debug for PyObjectObRefcnt {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        write!(f, "{}", unsafe { self.ob_refcnt })
92    }
93}
94
95#[cfg(all(not(Py_3_12), not(Py_GIL_DISABLED)))]
96pub type PyObjectObRefcnt = Py_ssize_t;
97
98#[repr(C)]
99#[derive(Debug)]
100pub struct PyObject {
101    #[cfg(py_sys_config = "Py_TRACE_REFS")]
102    pub _ob_next: *mut PyObject,
103    #[cfg(py_sys_config = "Py_TRACE_REFS")]
104    pub _ob_prev: *mut PyObject,
105    #[cfg(Py_GIL_DISABLED)]
106    pub ob_tid: libc::uintptr_t,
107    #[cfg(Py_GIL_DISABLED)]
108    pub _padding: u16,
109    #[cfg(Py_GIL_DISABLED)]
110    pub ob_mutex: PyMutex, // per-object lock
111    #[cfg(Py_GIL_DISABLED)]
112    pub ob_gc_bits: u8, // gc-related state
113    #[cfg(Py_GIL_DISABLED)]
114    pub ob_ref_local: AtomicU32, // local reference count
115    #[cfg(Py_GIL_DISABLED)]
116    pub ob_ref_shared: AtomicIsize, // shared reference count
117    #[cfg(not(Py_GIL_DISABLED))]
118    pub ob_refcnt: PyObjectObRefcnt,
119    #[cfg(PyPy)]
120    pub ob_pypy_link: Py_ssize_t,
121    pub ob_type: *mut PyTypeObject,
122}
123
124// skipped private _PyObject_CAST
125
126#[repr(C)]
127#[derive(Debug)]
128pub struct PyVarObject {
129    pub ob_base: PyObject,
130    #[cfg(not(GraalPy))]
131    pub ob_size: Py_ssize_t,
132    // On GraalPy the field is physically there, but not always populated. We hide it to prevent accidental misuse
133    #[cfg(GraalPy)]
134    pub _ob_size_graalpy: Py_ssize_t,
135}
136
137// skipped private _PyVarObject_CAST
138
139#[inline]
140#[cfg(not(all(PyPy, Py_3_10)))]
141#[cfg_attr(docsrs, doc(cfg(all())))]
142pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int {
143    (x == y).into()
144}
145
146#[cfg(all(PyPy, Py_3_10))]
147#[cfg_attr(docsrs, doc(cfg(all())))]
148extern "C" {
149    #[cfg_attr(PyPy, link_name = "PyPy_Is")]
150    pub fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int;
151}
152
153// skipped private _Py_GetThreadLocal_Addr
154
155// skipped private _Py_ThreadId
156
157// skipped private _Py_IsOwnedByCurrentThread
158
159#[inline]
160pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
161    #[cfg(Py_GIL_DISABLED)]
162    {
163        let local = (*ob).ob_ref_local.load(Relaxed);
164        if local == _Py_IMMORTAL_REFCNT_LOCAL {
165            return _Py_IMMORTAL_REFCNT;
166        }
167        let shared = (*ob).ob_ref_shared.load(Relaxed);
168        local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
169    }
170
171    #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
172    {
173        (*ob).ob_refcnt.ob_refcnt
174    }
175
176    #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]
177    {
178        (*ob).ob_refcnt
179    }
180
181    #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]
182    {
183        _Py_REFCNT(ob)
184    }
185}
186
187#[inline]
188pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
189    #[cfg(not(GraalPy))]
190    return (*ob).ob_type;
191    #[cfg(GraalPy)]
192    return _Py_TYPE(ob);
193}
194
195#[cfg_attr(windows, link(name = "pythonXY"))]
196extern "C" {
197    #[cfg_attr(PyPy, link_name = "PyPyLong_Type")]
198    pub static mut PyLong_Type: PyTypeObject;
199    #[cfg_attr(PyPy, link_name = "PyPyBool_Type")]
200    pub static mut PyBool_Type: PyTypeObject;
201}
202
203#[inline]
204pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {
205    #[cfg(not(GraalPy))]
206    {
207        debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyLong_Type));
208        debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyBool_Type));
209        (*ob.cast::<PyVarObject>()).ob_size
210    }
211    #[cfg(GraalPy)]
212    _Py_SIZE(ob)
213}
214
215#[inline(always)]
216#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
217unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
218    #[cfg(target_pointer_width = "64")]
219    {
220        (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
221    }
222
223    #[cfg(target_pointer_width = "32")]
224    {
225        ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
226    }
227}
228
229#[inline]
230pub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
231    (Py_TYPE(ob) == tp) as c_int
232}
233
234// skipped _Py_SetRefCnt
235
236// skipped Py_SET_REFCNT
237
238// skipped Py_SET_TYPE
239
240// skipped Py_SET_SIZE
241
242pub type unaryfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
243pub type binaryfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> *mut PyObject;
244pub type ternaryfunc =
245    unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject;
246pub type inquiry = unsafe extern "C" fn(*mut PyObject) -> c_int;
247pub type lenfunc = unsafe extern "C" fn(*mut PyObject) -> Py_ssize_t;
248pub type ssizeargfunc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t) -> *mut PyObject;
249pub type ssizessizeargfunc =
250    unsafe extern "C" fn(*mut PyObject, Py_ssize_t, Py_ssize_t) -> *mut PyObject;
251pub type ssizeobjargproc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t, *mut PyObject) -> c_int;
252pub type ssizessizeobjargproc =
253    unsafe extern "C" fn(*mut PyObject, Py_ssize_t, Py_ssize_t, arg4: *mut PyObject) -> c_int;
254pub type objobjargproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
255
256pub type objobjproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> c_int;
257pub type visitproc = unsafe extern "C" fn(object: *mut PyObject, arg: *mut c_void) -> c_int;
258pub type traverseproc =
259    unsafe extern "C" fn(slf: *mut PyObject, visit: visitproc, arg: *mut c_void) -> c_int;
260
261pub type freefunc = unsafe extern "C" fn(*mut c_void);
262pub type destructor = unsafe extern "C" fn(*mut PyObject);
263pub type getattrfunc = unsafe extern "C" fn(*mut PyObject, *mut c_char) -> *mut PyObject;
264pub type getattrofunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> *mut PyObject;
265pub type setattrfunc = unsafe extern "C" fn(*mut PyObject, *mut c_char, *mut PyObject) -> c_int;
266pub type setattrofunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
267pub type reprfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
268pub type hashfunc = unsafe extern "C" fn(*mut PyObject) -> Py_hash_t;
269pub type richcmpfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, c_int) -> *mut PyObject;
270pub type getiterfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
271pub type iternextfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
272pub type descrgetfunc =
273    unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject;
274pub type descrsetfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
275pub type initproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
276pub type newfunc =
277    unsafe extern "C" fn(*mut PyTypeObject, *mut PyObject, *mut PyObject) -> *mut PyObject;
278pub type allocfunc = unsafe extern "C" fn(*mut PyTypeObject, Py_ssize_t) -> *mut PyObject;
279
280#[cfg(Py_3_8)]
281pub type vectorcallfunc = unsafe extern "C" fn(
282    callable: *mut PyObject,
283    args: *const *mut PyObject,
284    nargsf: libc::size_t,
285    kwnames: *mut PyObject,
286) -> *mut PyObject;
287
288#[repr(C)]
289#[derive(Copy, Clone)]
290pub struct PyType_Slot {
291    pub slot: c_int,
292    pub pfunc: *mut c_void,
293}
294
295impl Default for PyType_Slot {
296    fn default() -> PyType_Slot {
297        unsafe { mem::zeroed() }
298    }
299}
300
301#[repr(C)]
302#[derive(Copy, Clone)]
303pub struct PyType_Spec {
304    pub name: *const c_char,
305    pub basicsize: c_int,
306    pub itemsize: c_int,
307    pub flags: c_uint,
308    pub slots: *mut PyType_Slot,
309}
310
311impl Default for PyType_Spec {
312    fn default() -> PyType_Spec {
313        unsafe { mem::zeroed() }
314    }
315}
316
317extern "C" {
318    #[cfg_attr(PyPy, link_name = "PyPyType_FromSpec")]
319    pub fn PyType_FromSpec(arg1: *mut PyType_Spec) -> *mut PyObject;
320
321    #[cfg_attr(PyPy, link_name = "PyPyType_FromSpecWithBases")]
322    pub fn PyType_FromSpecWithBases(arg1: *mut PyType_Spec, arg2: *mut PyObject) -> *mut PyObject;
323
324    #[cfg_attr(PyPy, link_name = "PyPyType_GetSlot")]
325    pub fn PyType_GetSlot(arg1: *mut PyTypeObject, arg2: c_int) -> *mut c_void;
326
327    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
328    #[cfg_attr(PyPy, link_name = "PyPyType_FromModuleAndSpec")]
329    pub fn PyType_FromModuleAndSpec(
330        module: *mut PyObject,
331        spec: *mut PyType_Spec,
332        bases: *mut PyObject,
333    ) -> *mut PyObject;
334
335    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
336    #[cfg_attr(PyPy, link_name = "PyPyType_GetModule")]
337    pub fn PyType_GetModule(arg1: *mut PyTypeObject) -> *mut PyObject;
338
339    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
340    #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleState")]
341    pub fn PyType_GetModuleState(arg1: *mut PyTypeObject) -> *mut c_void;
342
343    #[cfg(Py_3_11)]
344    #[cfg_attr(PyPy, link_name = "PyPyType_GetName")]
345    pub fn PyType_GetName(arg1: *mut PyTypeObject) -> *mut PyObject;
346
347    #[cfg(Py_3_11)]
348    #[cfg_attr(PyPy, link_name = "PyPyType_GetQualName")]
349    pub fn PyType_GetQualName(arg1: *mut PyTypeObject) -> *mut PyObject;
350
351    #[cfg(Py_3_13)]
352    #[cfg_attr(PyPy, link_name = "PyPyType_GetFullyQualifiedName")]
353    pub fn PyType_GetFullyQualifiedName(arg1: *mut PyTypeObject) -> *mut PyObject;
354
355    #[cfg(Py_3_13)]
356    #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleName")]
357    pub fn PyType_GetModuleName(arg1: *mut PyTypeObject) -> *mut PyObject;
358
359    #[cfg(Py_3_12)]
360    #[cfg_attr(PyPy, link_name = "PyPyType_FromMetaclass")]
361    pub fn PyType_FromMetaclass(
362        metaclass: *mut PyTypeObject,
363        module: *mut PyObject,
364        spec: *mut PyType_Spec,
365        bases: *mut PyObject,
366    ) -> *mut PyObject;
367
368    #[cfg(Py_3_12)]
369    #[cfg_attr(PyPy, link_name = "PyPyObject_GetTypeData")]
370    pub fn PyObject_GetTypeData(obj: *mut PyObject, cls: *mut PyTypeObject) -> *mut c_void;
371
372    #[cfg(Py_3_12)]
373    #[cfg_attr(PyPy, link_name = "PyPyObject_GetTypeDataSize")]
374    pub fn PyObject_GetTypeDataSize(cls: *mut PyTypeObject) -> Py_ssize_t;
375
376    #[cfg_attr(PyPy, link_name = "PyPyType_IsSubtype")]
377    pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int;
378}
379
380#[inline]
381pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
382    (Py_IS_TYPE(ob, tp) != 0 || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int
383}
384
385#[cfg_attr(windows, link(name = "pythonXY"))]
386extern "C" {
387    /// built-in 'type'
388    #[cfg_attr(PyPy, link_name = "PyPyType_Type")]
389    pub static mut PyType_Type: PyTypeObject;
390    /// built-in 'object'
391    #[cfg_attr(PyPy, link_name = "PyPyBaseObject_Type")]
392    pub static mut PyBaseObject_Type: PyTypeObject;
393    /// built-in 'super'
394    pub static mut PySuper_Type: PyTypeObject;
395}
396
397extern "C" {
398    pub fn PyType_GetFlags(arg1: *mut PyTypeObject) -> c_ulong;
399
400    #[cfg_attr(PyPy, link_name = "PyPyType_Ready")]
401    pub fn PyType_Ready(t: *mut PyTypeObject) -> c_int;
402    #[cfg_attr(PyPy, link_name = "PyPyType_GenericAlloc")]
403    pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject;
404    #[cfg_attr(PyPy, link_name = "PyPyType_GenericNew")]
405    pub fn PyType_GenericNew(
406        t: *mut PyTypeObject,
407        args: *mut PyObject,
408        kwds: *mut PyObject,
409    ) -> *mut PyObject;
410    pub fn PyType_ClearCache() -> c_uint;
411    #[cfg_attr(PyPy, link_name = "PyPyType_Modified")]
412    pub fn PyType_Modified(t: *mut PyTypeObject);
413
414    #[cfg_attr(PyPy, link_name = "PyPyObject_Repr")]
415    pub fn PyObject_Repr(o: *mut PyObject) -> *mut PyObject;
416    #[cfg_attr(PyPy, link_name = "PyPyObject_Str")]
417    pub fn PyObject_Str(o: *mut PyObject) -> *mut PyObject;
418    #[cfg_attr(PyPy, link_name = "PyPyObject_ASCII")]
419    pub fn PyObject_ASCII(arg1: *mut PyObject) -> *mut PyObject;
420    #[cfg_attr(PyPy, link_name = "PyPyObject_Bytes")]
421    pub fn PyObject_Bytes(arg1: *mut PyObject) -> *mut PyObject;
422    #[cfg_attr(PyPy, link_name = "PyPyObject_RichCompare")]
423    pub fn PyObject_RichCompare(
424        arg1: *mut PyObject,
425        arg2: *mut PyObject,
426        arg3: c_int,
427    ) -> *mut PyObject;
428    #[cfg_attr(PyPy, link_name = "PyPyObject_RichCompareBool")]
429    pub fn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int)
430        -> c_int;
431    #[cfg_attr(PyPy, link_name = "PyPyObject_GetAttrString")]
432    pub fn PyObject_GetAttrString(arg1: *mut PyObject, arg2: *const c_char) -> *mut PyObject;
433    #[cfg_attr(PyPy, link_name = "PyPyObject_SetAttrString")]
434    pub fn PyObject_SetAttrString(
435        arg1: *mut PyObject,
436        arg2: *const c_char,
437        arg3: *mut PyObject,
438    ) -> c_int;
439    #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h
440    #[cfg_attr(PyPy, link_name = "PyPyObject_DelAttrString")]
441    pub fn PyObject_DelAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
442    #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrString")]
443    pub fn PyObject_HasAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
444    #[cfg_attr(PyPy, link_name = "PyPyObject_GetAttr")]
445    pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
446    #[cfg(Py_3_13)]
447    #[cfg_attr(PyPy, link_name = "PyPyObject_GetOptionalAttr")]
448    pub fn PyObject_GetOptionalAttr(
449        arg1: *mut PyObject,
450        arg2: *mut PyObject,
451        arg3: *mut *mut PyObject,
452    ) -> c_int;
453    #[cfg(Py_3_13)]
454    #[cfg_attr(PyPy, link_name = "PyPyObject_GetOptionalAttrString")]
455    pub fn PyObject_GetOptionalAttrString(
456        arg1: *mut PyObject,
457        arg2: *const c_char,
458        arg3: *mut *mut PyObject,
459    ) -> c_int;
460    #[cfg_attr(PyPy, link_name = "PyPyObject_SetAttr")]
461    pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject)
462        -> c_int;
463    #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h
464    #[cfg_attr(PyPy, link_name = "PyPyObject_DelAttr")]
465    pub fn PyObject_DelAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
466    #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttr")]
467    pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
468    #[cfg(Py_3_13)]
469    #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrWithError")]
470    pub fn PyObject_HasAttrWithError(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
471    #[cfg(Py_3_13)]
472    #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrStringWithError")]
473    pub fn PyObject_HasAttrStringWithError(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
474    #[cfg_attr(PyPy, link_name = "PyPyObject_SelfIter")]
475    pub fn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject;
476    #[cfg_attr(PyPy, link_name = "PyPyObject_GenericGetAttr")]
477    pub fn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
478    #[cfg_attr(PyPy, link_name = "PyPyObject_GenericSetAttr")]
479    pub fn PyObject_GenericSetAttr(
480        arg1: *mut PyObject,
481        arg2: *mut PyObject,
482        arg3: *mut PyObject,
483    ) -> c_int;
484    #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))]
485    #[cfg_attr(PyPy, link_name = "PyPyObject_GenericGetDict")]
486    pub fn PyObject_GenericGetDict(arg1: *mut PyObject, arg2: *mut c_void) -> *mut PyObject;
487    #[cfg_attr(PyPy, link_name = "PyPyObject_GenericSetDict")]
488    pub fn PyObject_GenericSetDict(
489        arg1: *mut PyObject,
490        arg2: *mut PyObject,
491        arg3: *mut c_void,
492    ) -> c_int;
493    #[cfg_attr(PyPy, link_name = "PyPyObject_Hash")]
494    pub fn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t;
495    #[cfg_attr(PyPy, link_name = "PyPyObject_HashNotImplemented")]
496    pub fn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t;
497    #[cfg_attr(PyPy, link_name = "PyPyObject_IsTrue")]
498    pub fn PyObject_IsTrue(arg1: *mut PyObject) -> c_int;
499    #[cfg_attr(PyPy, link_name = "PyPyObject_Not")]
500    pub fn PyObject_Not(arg1: *mut PyObject) -> c_int;
501    #[cfg_attr(PyPy, link_name = "PyPyCallable_Check")]
502    pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int;
503    #[cfg_attr(PyPy, link_name = "PyPyObject_ClearWeakRefs")]
504    pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject);
505
506    #[cfg_attr(PyPy, link_name = "PyPyObject_Dir")]
507    pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject;
508    pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int;
509    pub fn Py_ReprLeave(arg1: *mut PyObject);
510}
511
512// Flag bits for printing:
513pub const Py_PRINT_RAW: c_int = 1; // No string quotes etc.
514
515// skipped because is a private API
516// const _Py_TPFLAGS_STATIC_BUILTIN: c_ulong = 1 << 1;
517
518#[cfg(all(Py_3_12, not(Py_LIMITED_API)))]
519pub const Py_TPFLAGS_MANAGED_WEAKREF: c_ulong = 1 << 3;
520
521#[cfg(all(Py_3_11, not(Py_LIMITED_API)))]
522pub const Py_TPFLAGS_MANAGED_DICT: c_ulong = 1 << 4;
523
524#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
525pub const Py_TPFLAGS_SEQUENCE: c_ulong = 1 << 5;
526
527#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
528pub const Py_TPFLAGS_MAPPING: c_ulong = 1 << 6;
529
530#[cfg(Py_3_10)]
531pub const Py_TPFLAGS_DISALLOW_INSTANTIATION: c_ulong = 1 << 7;
532
533#[cfg(Py_3_10)]
534pub const Py_TPFLAGS_IMMUTABLETYPE: c_ulong = 1 << 8;
535
536/// Set if the type object is dynamically allocated
537pub const Py_TPFLAGS_HEAPTYPE: c_ulong = 1 << 9;
538
539/// Set if the type allows subclassing
540pub const Py_TPFLAGS_BASETYPE: c_ulong = 1 << 10;
541
542/// Set if the type implements the vectorcall protocol (PEP 590)
543#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]
544pub const Py_TPFLAGS_HAVE_VECTORCALL: c_ulong = 1 << 11;
545// skipped backwards-compatibility alias _Py_TPFLAGS_HAVE_VECTORCALL
546
547/// Set if the type is 'ready' -- fully initialized
548pub const Py_TPFLAGS_READY: c_ulong = 1 << 12;
549
550/// Set while the type is being 'readied', to prevent recursive ready calls
551pub const Py_TPFLAGS_READYING: c_ulong = 1 << 13;
552
553/// Objects support garbage collection (see objimp.h)
554pub const Py_TPFLAGS_HAVE_GC: c_ulong = 1 << 14;
555
556const Py_TPFLAGS_HAVE_STACKLESS_EXTENSION: c_ulong = 0;
557
558#[cfg(Py_3_8)]
559pub const Py_TPFLAGS_METHOD_DESCRIPTOR: c_ulong = 1 << 17;
560
561pub const Py_TPFLAGS_VALID_VERSION_TAG: c_ulong = 1 << 19;
562
563/* Type is abstract and cannot be instantiated */
564pub const Py_TPFLAGS_IS_ABSTRACT: c_ulong = 1 << 20;
565
566// skipped non-limited / 3.10 Py_TPFLAGS_HAVE_AM_SEND
567#[cfg(Py_3_12)]
568pub const Py_TPFLAGS_ITEMS_AT_END: c_ulong = 1 << 23;
569
570/* These flags are used to determine if a type is a subclass. */
571pub const Py_TPFLAGS_LONG_SUBCLASS: c_ulong = 1 << 24;
572pub const Py_TPFLAGS_LIST_SUBCLASS: c_ulong = 1 << 25;
573pub const Py_TPFLAGS_TUPLE_SUBCLASS: c_ulong = 1 << 26;
574pub const Py_TPFLAGS_BYTES_SUBCLASS: c_ulong = 1 << 27;
575pub const Py_TPFLAGS_UNICODE_SUBCLASS: c_ulong = 1 << 28;
576pub const Py_TPFLAGS_DICT_SUBCLASS: c_ulong = 1 << 29;
577pub const Py_TPFLAGS_BASE_EXC_SUBCLASS: c_ulong = 1 << 30;
578pub const Py_TPFLAGS_TYPE_SUBCLASS: c_ulong = 1 << 31;
579
580pub const Py_TPFLAGS_DEFAULT: c_ulong = if cfg!(Py_3_10) {
581    Py_TPFLAGS_HAVE_STACKLESS_EXTENSION
582} else {
583    Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | Py_TPFLAGS_HAVE_VERSION_TAG
584};
585
586pub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1;
587pub const Py_TPFLAGS_HAVE_VERSION_TAG: c_ulong = 1 << 18;
588
589extern "C" {
590    #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
591    fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
592    #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
593    fn _Py_INCREF_IncRefTotal();
594    #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
595    fn _Py_DECREF_DecRefTotal();
596
597    #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
598    fn _Py_Dealloc(arg1: *mut PyObject);
599
600    #[cfg_attr(PyPy, link_name = "PyPy_IncRef")]
601    #[cfg_attr(GraalPy, link_name = "_Py_IncRef")]
602    pub fn Py_IncRef(o: *mut PyObject);
603    #[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
604    #[cfg_attr(GraalPy, link_name = "_Py_DecRef")]
605    pub fn Py_DecRef(o: *mut PyObject);
606
607    #[cfg(all(Py_3_10, not(PyPy)))]
608    fn _Py_IncRef(o: *mut PyObject);
609    #[cfg(all(Py_3_10, not(PyPy)))]
610    fn _Py_DecRef(o: *mut PyObject);
611
612    #[cfg(GraalPy)]
613    fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;
614
615    #[cfg(GraalPy)]
616    fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject;
617
618    #[cfg(GraalPy)]
619    fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t;
620}
621
622#[inline(always)]
623pub unsafe fn Py_INCREF(op: *mut PyObject) {
624    // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
625    // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
626    #[cfg(any(
627        Py_GIL_DISABLED,
628        Py_LIMITED_API,
629        py_sys_config = "Py_REF_DEBUG",
630        GraalPy
631    ))]
632    {
633        // _Py_IncRef was added to the ABI in 3.10; skips null checks
634        #[cfg(all(Py_3_10, not(PyPy)))]
635        {
636            _Py_IncRef(op);
637        }
638
639        #[cfg(any(not(Py_3_10), PyPy))]
640        {
641            Py_IncRef(op);
642        }
643    }
644
645    // version-specific builds are allowed to directly manipulate the reference count
646    #[cfg(not(any(
647        Py_GIL_DISABLED,
648        Py_LIMITED_API,
649        py_sys_config = "Py_REF_DEBUG",
650        GraalPy
651    )))]
652    {
653        #[cfg(all(Py_3_12, target_pointer_width = "64"))]
654        {
655            let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
656            let new_refcnt = cur_refcnt.wrapping_add(1);
657            if new_refcnt == 0 {
658                return;
659            }
660            (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
661        }
662
663        #[cfg(all(Py_3_12, target_pointer_width = "32"))]
664        {
665            if _Py_IsImmortal(op) != 0 {
666                return;
667            }
668            (*op).ob_refcnt.ob_refcnt += 1
669        }
670
671        #[cfg(not(Py_3_12))]
672        {
673            (*op).ob_refcnt += 1
674        }
675
676        // Skipped _Py_INCREF_STAT_INC - if anyone wants this, please file an issue
677        // or submit a PR supporting Py_STATS build option and pystats.h
678    }
679}
680
681#[inline(always)]
682#[cfg_attr(
683    all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
684    track_caller
685)]
686pub unsafe fn Py_DECREF(op: *mut PyObject) {
687    // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
688    // On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts
689    // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
690    #[cfg(any(
691        Py_GIL_DISABLED,
692        Py_LIMITED_API,
693        all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
694        GraalPy
695    ))]
696    {
697        // _Py_DecRef was added to the ABI in 3.10; skips null checks
698        #[cfg(all(Py_3_10, not(PyPy)))]
699        {
700            _Py_DecRef(op);
701        }
702
703        #[cfg(any(not(Py_3_10), PyPy))]
704        {
705            Py_DecRef(op);
706        }
707    }
708
709    #[cfg(not(any(
710        Py_GIL_DISABLED,
711        Py_LIMITED_API,
712        all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
713        GraalPy
714    )))]
715    {
716        #[cfg(Py_3_12)]
717        if _Py_IsImmortal(op) != 0 {
718            return;
719        }
720
721        // Skipped _Py_DECREF_STAT_INC - if anyone needs this, please file an issue
722        // or submit a PR supporting Py_STATS build option and pystats.h
723
724        #[cfg(py_sys_config = "Py_REF_DEBUG")]
725        _Py_DECREF_DecRefTotal();
726
727        #[cfg(Py_3_12)]
728        {
729            (*op).ob_refcnt.ob_refcnt -= 1;
730
731            #[cfg(py_sys_config = "Py_REF_DEBUG")]
732            if (*op).ob_refcnt.ob_refcnt < 0 {
733                let location = std::panic::Location::caller();
734                let filename = std::ffi::CString::new(location.file()).unwrap();
735                _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
736            }
737
738            if (*op).ob_refcnt.ob_refcnt == 0 {
739                _Py_Dealloc(op);
740            }
741        }
742
743        #[cfg(not(Py_3_12))]
744        {
745            (*op).ob_refcnt -= 1;
746
747            if (*op).ob_refcnt == 0 {
748                _Py_Dealloc(op);
749            }
750        }
751    }
752}
753
754#[inline]
755pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
756    let tmp = *op;
757    if !tmp.is_null() {
758        *op = ptr::null_mut();
759        Py_DECREF(tmp);
760    }
761}
762
763#[inline]
764pub unsafe fn Py_XINCREF(op: *mut PyObject) {
765    if !op.is_null() {
766        Py_INCREF(op)
767    }
768}
769
770#[inline]
771pub unsafe fn Py_XDECREF(op: *mut PyObject) {
772    if !op.is_null() {
773        Py_DECREF(op)
774    }
775}
776
777extern "C" {
778    #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
779    #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
780    pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
781    #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
782    #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
783    pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
784}
785
786// macro _Py_NewRef not public; reimplemented directly inside Py_NewRef here
787// macro _Py_XNewRef not public; reimplemented directly inside Py_XNewRef here
788
789#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
790#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
791#[inline]
792pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
793    Py_INCREF(obj);
794    obj
795}
796
797#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
798#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
799#[inline]
800pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
801    Py_XINCREF(obj);
802    obj
803}
804
805#[cfg(Py_3_13)]
806pub const Py_CONSTANT_NONE: c_uint = 0;
807#[cfg(Py_3_13)]
808pub const Py_CONSTANT_FALSE: c_uint = 1;
809#[cfg(Py_3_13)]
810pub const Py_CONSTANT_TRUE: c_uint = 2;
811#[cfg(Py_3_13)]
812pub const Py_CONSTANT_ELLIPSIS: c_uint = 3;
813#[cfg(Py_3_13)]
814pub const Py_CONSTANT_NOT_IMPLEMENTED: c_uint = 4;
815#[cfg(Py_3_13)]
816pub const Py_CONSTANT_ZERO: c_uint = 5;
817#[cfg(Py_3_13)]
818pub const Py_CONSTANT_ONE: c_uint = 6;
819#[cfg(Py_3_13)]
820pub const Py_CONSTANT_EMPTY_STR: c_uint = 7;
821#[cfg(Py_3_13)]
822pub const Py_CONSTANT_EMPTY_BYTES: c_uint = 8;
823#[cfg(Py_3_13)]
824pub const Py_CONSTANT_EMPTY_TUPLE: c_uint = 9;
825
826extern "C" {
827    #[cfg(Py_3_13)]
828    #[cfg_attr(PyPy, link_name = "PyPy_GetConstant")]
829    pub fn Py_GetConstant(constant_id: c_uint) -> *mut PyObject;
830    #[cfg(Py_3_13)]
831    #[cfg_attr(PyPy, link_name = "PyPy_GetConstantBorrowed")]
832    pub fn Py_GetConstantBorrowed(constant_id: c_uint) -> *mut PyObject;
833}
834
835#[cfg_attr(windows, link(name = "pythonXY"))]
836extern "C" {
837    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
838    #[cfg_attr(PyPy, link_name = "_PyPy_NoneStruct")]
839    static mut _Py_NoneStruct: PyObject;
840
841    #[cfg(GraalPy)]
842    static mut _Py_NoneStructReference: *mut PyObject;
843}
844
845#[inline]
846pub unsafe fn Py_None() -> *mut PyObject {
847    #[cfg(all(not(GraalPy), all(Py_3_13, Py_LIMITED_API)))]
848    return Py_GetConstantBorrowed(Py_CONSTANT_NONE);
849
850    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
851    return ptr::addr_of_mut!(_Py_NoneStruct);
852
853    #[cfg(GraalPy)]
854    return _Py_NoneStructReference;
855}
856
857#[inline]
858pub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int {
859    Py_Is(x, Py_None())
860}
861
862// skipped Py_RETURN_NONE
863
864#[cfg_attr(windows, link(name = "pythonXY"))]
865extern "C" {
866    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
867    #[cfg_attr(PyPy, link_name = "_PyPy_NotImplementedStruct")]
868    static mut _Py_NotImplementedStruct: PyObject;
869
870    #[cfg(GraalPy)]
871    static mut _Py_NotImplementedStructReference: *mut PyObject;
872}
873
874#[inline]
875pub unsafe fn Py_NotImplemented() -> *mut PyObject {
876    #[cfg(all(not(GraalPy), all(Py_3_13, Py_LIMITED_API)))]
877    return Py_GetConstantBorrowed(Py_CONSTANT_NOT_IMPLEMENTED);
878
879    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
880    return ptr::addr_of_mut!(_Py_NotImplementedStruct);
881
882    #[cfg(GraalPy)]
883    return _Py_NotImplementedStructReference;
884}
885
886// skipped Py_RETURN_NOTIMPLEMENTED
887
888/* Rich comparison opcodes */
889pub const Py_LT: c_int = 0;
890pub const Py_LE: c_int = 1;
891pub const Py_EQ: c_int = 2;
892pub const Py_NE: c_int = 3;
893pub const Py_GT: c_int = 4;
894pub const Py_GE: c_int = 5;
895
896#[cfg(Py_3_10)]
897#[repr(C)]
898#[derive(Copy, Clone, Debug, PartialEq, Eq)]
899pub enum PySendResult {
900    PYGEN_RETURN = 0,
901    PYGEN_ERROR = -1,
902    PYGEN_NEXT = 1,
903}
904
905// skipped Py_RETURN_RICHCOMPARE
906
907#[inline]
908pub unsafe fn PyType_HasFeature(ty: *mut PyTypeObject, feature: c_ulong) -> c_int {
909    #[cfg(Py_LIMITED_API)]
910    let flags = PyType_GetFlags(ty);
911
912    #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
913    let flags = (*ty).tp_flags.load(std::sync::atomic::Ordering::Relaxed);
914
915    #[cfg(all(not(Py_LIMITED_API), not(Py_GIL_DISABLED)))]
916    let flags = (*ty).tp_flags;
917
918    ((flags & feature) != 0) as c_int
919}
920
921#[inline]
922pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int {
923    PyType_HasFeature(t, f)
924}
925
926#[inline]
927pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
928    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS)
929}
930
931// skipped _PyType_CAST
932
933#[inline]
934pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {
935    Py_IS_TYPE(op, ptr::addr_of_mut!(PyType_Type))
936}
937
938extern "C" {
939    #[cfg(any(Py_3_13, all(Py_3_11, not(Py_LIMITED_API))))]
940    #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleByDef")]
941    pub fn PyType_GetModuleByDef(
942        arg1: *mut crate::PyTypeObject,
943        arg2: *mut crate::PyModuleDef,
944    ) -> *mut PyObject;
945}