Skip to main content

pyo3_ffi/
object.rs

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