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