Skip to main content

pyforge_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 PyForge 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 PyForge 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 PyForge 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    pub ob_type: *mut PyTypeObject,
115}
116
117const _: () = assert!(std::mem::align_of::<PyObject>() >= _PyObject_MIN_ALIGNMENT);
118
119#[allow(
120    clippy::declare_interior_mutable_const,
121    reason = "contains atomic refcount on free-threaded builds"
122)]
123pub const PyObject_HEAD_INIT: PyObject = PyObject {
124    #[cfg(Py_GIL_DISABLED)]
125    ob_tid: 0,
126    #[cfg(all(Py_GIL_DISABLED, Py_3_15))]
127    ob_flags: refcount::_Py_STATICALLY_ALLOCATED_FLAG as u16,
128    #[cfg(all(Py_GIL_DISABLED, all(Py_3_14, not(Py_3_15))))]
129    ob_flags: 0,
130    #[cfg(all(Py_GIL_DISABLED, not(Py_3_14)))]
131    _padding: 0,
132    #[cfg(Py_GIL_DISABLED)]
133    ob_mutex: PyMutex::new(),
134    #[cfg(Py_GIL_DISABLED)]
135    ob_gc_bits: 0,
136    #[cfg(Py_GIL_DISABLED)]
137    ob_ref_local: AtomicU32::new(refcount::_Py_IMMORTAL_REFCNT_LOCAL),
138    #[cfg(Py_GIL_DISABLED)]
139    ob_ref_shared: AtomicIsize::new(0),
140    #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
141    ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 },
142    #[cfg(not(Py_3_12))]
143    ob_refcnt: 1,
144    ob_type: std::ptr::null_mut(),
145};
146
147// skipped _Py_UNOWNED_TID
148
149// skipped _PyObject_CAST
150
151#[repr(C)]
152#[derive(Debug)]
153pub struct PyVarObject {
154    pub ob_base: PyObject,
155    pub ob_size: Py_ssize_t,
156}
157
158// skipped private _PyVarObject_CAST
159
160#[inline]
161#[cfg_attr(docsrs, doc(cfg(all())))]
162pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int {
163    (x == y).into()
164}
165
166// skipped _Py_GetThreadLocal_Addr
167
168// skipped _Py_ThreadID
169
170// skipped _Py_IsOwnedByCurrentThread
171
172#[inline]
173#[cfg(not(Py_3_14))]
174pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
175    (*ob).ob_type
176}
177
178#[cfg(Py_3_14)]
179extern_libpython! {
180    pub fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject;
181}
182
183// skip _Py_TYPE compat shim
184
185extern_libpython! {
186    pub static mut PyLong_Type: PyTypeObject;
187    pub static mut PyBool_Type: PyTypeObject;
188}
189
190#[inline]
191pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {
192    debug_assert_ne!((*ob).ob_type, &raw mut crate::PyLong_Type);
193    debug_assert_ne!((*ob).ob_type, &raw mut crate::PyBool_Type);
194    (*ob.cast::<PyVarObject>()).ob_size
195}
196
197#[inline]
198pub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
199    (Py_TYPE(ob) == tp) as c_int
200}
201
202// skipped Py_SET_TYPE
203
204// skipped Py_SET_SIZE
205
206pub type unaryfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
207pub type binaryfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> *mut PyObject;
208pub type ternaryfunc =
209    unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject;
210pub type inquiry = unsafe extern "C" fn(*mut PyObject) -> c_int;
211pub type lenfunc = unsafe extern "C" fn(*mut PyObject) -> Py_ssize_t;
212pub type ssizeargfunc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t) -> *mut PyObject;
213pub type ssizessizeargfunc =
214    unsafe extern "C" fn(*mut PyObject, Py_ssize_t, Py_ssize_t) -> *mut PyObject;
215pub type ssizeobjargproc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t, *mut PyObject) -> c_int;
216pub type ssizessizeobjargproc =
217    unsafe extern "C" fn(*mut PyObject, Py_ssize_t, Py_ssize_t, arg4: *mut PyObject) -> c_int;
218pub type objobjargproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
219
220pub type objobjproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> c_int;
221pub type visitproc = unsafe extern "C" fn(object: *mut PyObject, arg: *mut c_void) -> c_int;
222pub type traverseproc =
223    unsafe extern "C" fn(slf: *mut PyObject, visit: visitproc, arg: *mut c_void) -> c_int;
224
225pub type freefunc = unsafe extern "C" fn(*mut c_void);
226pub type destructor = unsafe extern "C" fn(*mut PyObject);
227pub type getattrfunc = unsafe extern "C" fn(*mut PyObject, *mut c_char) -> *mut PyObject;
228pub type getattrofunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> *mut PyObject;
229pub type setattrfunc = unsafe extern "C" fn(*mut PyObject, *mut c_char, *mut PyObject) -> c_int;
230pub type setattrofunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
231pub type reprfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
232pub type hashfunc = unsafe extern "C" fn(*mut PyObject) -> Py_hash_t;
233pub type richcmpfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, c_int) -> *mut PyObject;
234pub type getiterfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
235pub type iternextfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject;
236pub type descrgetfunc =
237    unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject;
238pub type descrsetfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
239pub type initproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;
240pub type newfunc =
241    unsafe extern "C" fn(*mut PyTypeObject, *mut PyObject, *mut PyObject) -> *mut PyObject;
242pub type allocfunc = unsafe extern "C" fn(*mut PyTypeObject, Py_ssize_t) -> *mut PyObject;
243pub type vectorcallfunc = unsafe extern "C" fn(
244    callable: *mut PyObject,
245    args: *const *mut PyObject,
246    nargsf: libc::size_t,
247    kwnames: *mut PyObject,
248) -> *mut PyObject;
249
250#[repr(C)]
251#[derive(Copy, Clone)]
252pub struct PyType_Slot {
253    pub slot: c_int,
254    pub pfunc: *mut c_void,
255}
256
257impl Default for PyType_Slot {
258    fn default() -> PyType_Slot {
259        unsafe { mem::zeroed() }
260    }
261}
262
263#[repr(C)]
264#[derive(Copy, Clone)]
265pub struct PyType_Spec {
266    pub name: *const c_char,
267    pub basicsize: c_int,
268    pub itemsize: c_int,
269    pub flags: c_uint,
270    pub slots: *mut PyType_Slot,
271}
272
273impl Default for PyType_Spec {
274    fn default() -> PyType_Spec {
275        unsafe { mem::zeroed() }
276    }
277}
278
279extern_libpython! {
280    pub fn PyType_FromSpec(arg1: *mut PyType_Spec) -> *mut PyObject;
281
282    pub fn PyType_FromSpecWithBases(arg1: *mut PyType_Spec, arg2: *mut PyObject) -> *mut PyObject;
283
284    pub fn PyType_GetSlot(arg1: *mut PyTypeObject, arg2: c_int) -> *mut c_void;
285
286    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
287    pub fn PyType_FromModuleAndSpec(
288        module: *mut PyObject,
289        spec: *mut PyType_Spec,
290        bases: *mut PyObject,
291    ) -> *mut PyObject;
292
293    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
294    pub fn PyType_GetModule(arg1: *mut PyTypeObject) -> *mut PyObject;
295
296    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
297    pub fn PyType_GetModuleState(arg1: *mut PyTypeObject) -> *mut c_void;
298
299    #[cfg(Py_3_11)]
300    pub fn PyType_GetName(arg1: *mut PyTypeObject) -> *mut PyObject;
301
302    #[cfg(Py_3_11)]
303    pub fn PyType_GetQualName(arg1: *mut PyTypeObject) -> *mut PyObject;
304
305    #[cfg(Py_3_13)]
306    pub fn PyType_GetFullyQualifiedName(arg1: *mut PyTypeObject) -> *mut PyObject;
307
308    #[cfg(Py_3_13)]
309    pub fn PyType_GetModuleName(arg1: *mut PyTypeObject) -> *mut PyObject;
310
311    #[cfg(Py_3_12)]
312    pub fn PyType_FromMetaclass(
313        metaclass: *mut PyTypeObject,
314        module: *mut PyObject,
315        spec: *mut PyType_Spec,
316        bases: *mut PyObject,
317    ) -> *mut PyObject;
318
319    #[cfg(Py_3_12)]
320    pub fn PyObject_GetTypeData(obj: *mut PyObject, cls: *mut PyTypeObject) -> *mut c_void;
321
322    #[cfg(Py_3_12)]
323    pub fn PyType_GetTypeDataSize(cls: *mut PyTypeObject) -> Py_ssize_t;
324
325    pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int;
326}
327
328#[inline]
329pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
330    (Py_IS_TYPE(ob, tp) != 0 || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int
331}
332
333extern_libpython! {
334    /// built-in 'type'
335    pub static mut PyType_Type: PyTypeObject;
336    /// built-in 'object'
337    pub static mut PyBaseObject_Type: PyTypeObject;
338    /// built-in 'super'
339    pub static mut PySuper_Type: PyTypeObject;
340}
341
342extern_libpython! {
343    pub fn PyType_GetFlags(arg1: *mut PyTypeObject) -> c_ulong;
344
345    pub fn PyType_Ready(t: *mut PyTypeObject) -> c_int;
346    pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject;
347    pub fn PyType_GenericNew(
348        t: *mut PyTypeObject,
349        args: *mut PyObject,
350        kwds: *mut PyObject,
351    ) -> *mut PyObject;
352    pub fn PyType_ClearCache() -> c_uint;
353    pub fn PyType_Modified(t: *mut PyTypeObject);
354
355    pub fn PyObject_Repr(o: *mut PyObject) -> *mut PyObject;
356    pub fn PyObject_Str(o: *mut PyObject) -> *mut PyObject;
357    pub fn PyObject_ASCII(arg1: *mut PyObject) -> *mut PyObject;
358    pub fn PyObject_Bytes(arg1: *mut PyObject) -> *mut PyObject;
359    pub fn PyObject_RichCompare(
360        arg1: *mut PyObject,
361        arg2: *mut PyObject,
362        arg3: c_int,
363    ) -> *mut PyObject;
364    pub fn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int)
365        -> c_int;
366    pub fn PyObject_GetAttrString(arg1: *mut PyObject, arg2: *const c_char) -> *mut PyObject;
367    pub fn PyObject_SetAttrString(
368        arg1: *mut PyObject,
369        arg2: *const c_char,
370        arg3: *mut PyObject,
371    ) -> c_int;
372    #[cfg(Py_3_13)] // CPython defined in 3.12 as an inline function in abstract.h
373    pub fn PyObject_DelAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
374    pub fn PyObject_HasAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
375    pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
376    #[cfg(Py_3_13)]
377    pub fn PyObject_GetOptionalAttr(
378        arg1: *mut PyObject,
379        arg2: *mut PyObject,
380        arg3: *mut *mut PyObject,
381    ) -> c_int;
382    #[cfg(Py_3_13)]
383    pub fn PyObject_GetOptionalAttrString(
384        arg1: *mut PyObject,
385        arg2: *const c_char,
386        arg3: *mut *mut PyObject,
387    ) -> c_int;
388    pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject)
389        -> c_int;
390    #[cfg(Py_3_13)] // CPython defined in 3.12 as an inline function in abstract.h
391    pub fn PyObject_DelAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
392    pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
393    #[cfg(Py_3_13)]
394    pub fn PyObject_HasAttrWithError(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
395    #[cfg(Py_3_13)]
396    pub fn PyObject_HasAttrStringWithError(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
397    pub fn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject;
398    pub fn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
399    pub fn PyObject_GenericSetAttr(
400        arg1: *mut PyObject,
401        arg2: *mut PyObject,
402        arg3: *mut PyObject,
403    ) -> c_int;
404    #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))]
405    pub fn PyObject_GenericGetDict(arg1: *mut PyObject, arg2: *mut c_void) -> *mut PyObject;
406    pub fn PyObject_GenericSetDict(
407        arg1: *mut PyObject,
408        arg2: *mut PyObject,
409        arg3: *mut c_void,
410    ) -> c_int;
411    pub fn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t;
412    pub fn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t;
413    pub fn PyObject_IsTrue(arg1: *mut PyObject) -> c_int;
414    pub fn PyObject_Not(arg1: *mut PyObject) -> c_int;
415    pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int;
416    pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject);
417
418    pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject;
419    pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int;
420    pub fn Py_ReprLeave(arg1: *mut PyObject);
421}
422
423// Flag bits for printing:
424pub const Py_PRINT_RAW: c_int = 1; // No string quotes etc.
425
426// skipped because is a private API
427// const _Py_TPFLAGS_STATIC_BUILTIN: c_ulong = 1 << 1;
428
429#[cfg(all(Py_3_12, not(Py_LIMITED_API)))]
430pub const Py_TPFLAGS_MANAGED_WEAKREF: c_ulong = 1 << 3;
431
432#[cfg(all(Py_3_11, not(Py_LIMITED_API)))]
433pub const Py_TPFLAGS_MANAGED_DICT: c_ulong = 1 << 4;
434
435#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
436pub const Py_TPFLAGS_SEQUENCE: c_ulong = 1 << 5;
437
438#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
439pub const Py_TPFLAGS_MAPPING: c_ulong = 1 << 6;
440
441#[cfg(Py_3_10)]
442pub const Py_TPFLAGS_DISALLOW_INSTANTIATION: c_ulong = 1 << 7;
443
444#[cfg(Py_3_10)]
445pub const Py_TPFLAGS_IMMUTABLETYPE: c_ulong = 1 << 8;
446
447/// Set if the type object is dynamically allocated
448pub const Py_TPFLAGS_HEAPTYPE: c_ulong = 1 << 9;
449
450/// Set if the type allows subclassing
451pub const Py_TPFLAGS_BASETYPE: c_ulong = 1 << 10;
452
453/// Set if the type implements the vectorcall protocol (PEP 590)
454#[cfg(any(Py_3_12, not(Py_LIMITED_API)))]
455pub const Py_TPFLAGS_HAVE_VECTORCALL: c_ulong = 1 << 11;
456// skipped backwards-compatibility alias _Py_TPFLAGS_HAVE_VECTORCALL
457
458/// Set if the type is 'ready' -- fully initialized
459pub const Py_TPFLAGS_READY: c_ulong = 1 << 12;
460
461/// Set while the type is being 'readied', to prevent recursive ready calls
462pub const Py_TPFLAGS_READYING: c_ulong = 1 << 13;
463
464/// Objects support garbage collection (see objimp.h)
465pub const Py_TPFLAGS_HAVE_GC: c_ulong = 1 << 14;
466
467const Py_TPFLAGS_HAVE_STACKLESS_EXTENSION: c_ulong = 0;
468pub const Py_TPFLAGS_METHOD_DESCRIPTOR: c_ulong = 1 << 17;
469
470pub const Py_TPFLAGS_VALID_VERSION_TAG: c_ulong = 1 << 19;
471
472/* Type is abstract and cannot be instantiated */
473pub const Py_TPFLAGS_IS_ABSTRACT: c_ulong = 1 << 20;
474
475// skipped non-limited / 3.10 Py_TPFLAGS_HAVE_AM_SEND
476#[cfg(Py_3_12)]
477pub const Py_TPFLAGS_ITEMS_AT_END: c_ulong = 1 << 23;
478
479/* These flags are used to determine if a type is a subclass. */
480pub const Py_TPFLAGS_LONG_SUBCLASS: c_ulong = 1 << 24;
481pub const Py_TPFLAGS_LIST_SUBCLASS: c_ulong = 1 << 25;
482pub const Py_TPFLAGS_TUPLE_SUBCLASS: c_ulong = 1 << 26;
483pub const Py_TPFLAGS_BYTES_SUBCLASS: c_ulong = 1 << 27;
484pub const Py_TPFLAGS_UNICODE_SUBCLASS: c_ulong = 1 << 28;
485pub const Py_TPFLAGS_DICT_SUBCLASS: c_ulong = 1 << 29;
486pub const Py_TPFLAGS_BASE_EXC_SUBCLASS: c_ulong = 1 << 30;
487pub const Py_TPFLAGS_TYPE_SUBCLASS: c_ulong = 1 << 31;
488
489pub const Py_TPFLAGS_DEFAULT: c_ulong = if cfg!(Py_3_10) {
490    Py_TPFLAGS_HAVE_STACKLESS_EXTENSION
491} else {
492    Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | Py_TPFLAGS_HAVE_VERSION_TAG
493};
494
495pub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1;
496pub const Py_TPFLAGS_HAVE_VERSION_TAG: c_ulong = 1 << 18;
497
498#[cfg(Py_3_13)]
499pub const Py_CONSTANT_NONE: c_uint = 0;
500#[cfg(Py_3_13)]
501pub const Py_CONSTANT_FALSE: c_uint = 1;
502#[cfg(Py_3_13)]
503pub const Py_CONSTANT_TRUE: c_uint = 2;
504#[cfg(Py_3_13)]
505pub const Py_CONSTANT_ELLIPSIS: c_uint = 3;
506#[cfg(Py_3_13)]
507pub const Py_CONSTANT_NOT_IMPLEMENTED: c_uint = 4;
508#[cfg(Py_3_13)]
509pub const Py_CONSTANT_ZERO: c_uint = 5;
510#[cfg(Py_3_13)]
511pub const Py_CONSTANT_ONE: c_uint = 6;
512#[cfg(Py_3_13)]
513pub const Py_CONSTANT_EMPTY_STR: c_uint = 7;
514#[cfg(Py_3_13)]
515pub const Py_CONSTANT_EMPTY_BYTES: c_uint = 8;
516#[cfg(Py_3_13)]
517pub const Py_CONSTANT_EMPTY_TUPLE: c_uint = 9;
518
519extern_libpython! {
520    #[cfg(Py_3_13)]
521    pub fn Py_GetConstant(constant_id: c_uint) -> *mut PyObject;
522    #[cfg(Py_3_13)]
523    pub fn Py_GetConstantBorrowed(constant_id: c_uint) -> *mut PyObject;
524}
525
526extern_libpython! {
527    #[cfg(not(all(Py_3_13, Py_LIMITED_API)))]
528    static mut _Py_NoneStruct: PyObject;
529}
530
531#[inline]
532pub unsafe fn Py_None() -> *mut PyObject {
533    #[cfg(all(Py_3_13, Py_LIMITED_API))]
534    return Py_GetConstantBorrowed(Py_CONSTANT_NONE);
535
536    #[cfg(not(all(Py_3_13, Py_LIMITED_API)))]
537    return &raw mut _Py_NoneStruct;
538}
539
540#[inline]
541pub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int {
542    Py_Is(x, Py_None())
543}
544
545// skipped Py_RETURN_NONE
546
547extern_libpython! {
548    #[cfg(not(all(Py_3_13, Py_LIMITED_API)))]
549    static mut _Py_NotImplementedStruct: PyObject;
550}
551
552#[inline]
553pub unsafe fn Py_NotImplemented() -> *mut PyObject {
554    #[cfg(all(Py_3_13, Py_LIMITED_API))]
555    return Py_GetConstantBorrowed(Py_CONSTANT_NOT_IMPLEMENTED);
556
557    #[cfg(not(all(Py_3_13, Py_LIMITED_API)))]
558    return &raw mut _Py_NotImplementedStruct;
559}
560
561// skipped Py_RETURN_NOTIMPLEMENTED
562
563/* Rich comparison opcodes */
564pub const Py_LT: c_int = 0;
565pub const Py_LE: c_int = 1;
566pub const Py_EQ: c_int = 2;
567pub const Py_NE: c_int = 3;
568pub const Py_GT: c_int = 4;
569pub const Py_GE: c_int = 5;
570
571#[cfg(Py_3_10)]
572#[repr(C)]
573#[derive(Copy, Clone, Debug, PartialEq, Eq)]
574pub enum PySendResult {
575    PYGEN_RETURN = 0,
576    PYGEN_ERROR = -1,
577    PYGEN_NEXT = 1,
578}
579
580// skipped Py_RETURN_RICHCOMPARE
581
582#[inline]
583pub unsafe fn PyType_HasFeature(ty: *mut PyTypeObject, feature: c_ulong) -> c_int {
584    #[cfg(Py_LIMITED_API)]
585    let flags = PyType_GetFlags(ty);
586
587    #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
588    let flags = (*ty).tp_flags.load(std::sync::atomic::Ordering::Relaxed);
589
590    #[cfg(all(not(Py_LIMITED_API), not(Py_GIL_DISABLED)))]
591    let flags = (*ty).tp_flags;
592
593    ((flags & feature) != 0) as c_int
594}
595
596#[inline]
597pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int {
598    PyType_HasFeature(t, f)
599}
600
601#[inline]
602pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
603    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS)
604}
605
606// skipped _PyType_CAST
607
608#[inline]
609pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {
610    Py_IS_TYPE(op, &raw mut PyType_Type)
611}
612
613extern_libpython! {
614    #[cfg(any(Py_3_13, all(Py_3_11, not(Py_LIMITED_API))))]
615    pub fn PyType_GetModuleByDef(
616        arg1: *mut crate::PyTypeObject,
617        arg2: *mut crate::PyModuleDef,
618    ) -> *mut PyObject;
619
620    #[cfg(Py_3_14)]
621    pub fn PyType_Freeze(tp: *mut crate::PyTypeObject) -> c_int;
622
623    #[cfg(Py_3_15)]
624    pub fn PyType_GetModuleByToken(_type: *mut PyTypeObject, token: *const c_void)
625        -> *mut PyObject;
626}