pyo3_ffi/
object.rs

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