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