1use crate::pyport::{Py_hash_t, Py_ssize_t};
2#[cfg(Py_GIL_DISABLED)]
3use crate::PyMutex;
4#[cfg(Py_GIL_DISABLED)]
5use std::marker::PhantomPinned;
6use std::mem;
7use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void};
8use std::ptr;
9#[cfg(Py_GIL_DISABLED)]
10use std::sync::atomic::{AtomicIsize, AtomicU32, AtomicU8, Ordering::Relaxed};
11
12#[cfg(Py_LIMITED_API)]
13opaque_struct!(PyTypeObject);
14
15#[cfg(not(Py_LIMITED_API))]
16pub use crate::cpython::object::PyTypeObject;
17
18#[cfg(Py_3_12)]
19const _Py_IMMORTAL_REFCNT: Py_ssize_t = {
20 if cfg!(target_pointer_width = "64") {
21 c_uint::MAX as Py_ssize_t
22 } else {
23 // for 32-bit systems, use the lower 30 bits (see comment in CPython's object.h)
24 (c_uint::MAX >> 2) as Py_ssize_t
25 }
26};
27
28#[cfg(Py_GIL_DISABLED)]
29const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
30
31#[allow(clippy::declare_interior_mutable_const)]
32pub const PyObject_HEAD_INIT: PyObject = PyObject {
33 #[cfg(py_sys_config = "Py_TRACE_REFS")]
34 _ob_next: std::ptr::null_mut(),
35 #[cfg(py_sys_config = "Py_TRACE_REFS")]
36 _ob_prev: std::ptr::null_mut(),
37 #[cfg(Py_GIL_DISABLED)]
38 ob_tid: 0,
39 #[cfg(Py_GIL_DISABLED)]
40 _padding: 0,
41 #[cfg(Py_GIL_DISABLED)]
42 ob_mutex: PyMutex {
43 _bits: AtomicU8::new(0),
44 _pin: PhantomPinned,
45 },
46 #[cfg(Py_GIL_DISABLED)]
47 ob_gc_bits: 0,
48 #[cfg(Py_GIL_DISABLED)]
49 ob_ref_local: AtomicU32::new(_Py_IMMORTAL_REFCNT_LOCAL),
50 #[cfg(Py_GIL_DISABLED)]
51 ob_ref_shared: AtomicIsize::new(0),
52 #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
53 ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 },
54 #[cfg(not(Py_3_12))]
55 ob_refcnt: 1,
56 #[cfg(PyPy)]
57 ob_pypy_link: 0,
58 ob_type: std::ptr::null_mut(),
59};
60
61// skipped PyObject_VAR_HEAD
62// skipped Py_INVALID_SIZE
63
64// skipped private _Py_UNOWNED_TID
65
66#[cfg(Py_GIL_DISABLED)]
67const _Py_REF_SHARED_SHIFT: isize = 2;
68// skipped private _Py_REF_SHARED_FLAG_MASK
69
70// skipped private _Py_REF_SHARED_INIT
71// skipped private _Py_REF_MAYBE_WEAKREF
72// skipped private _Py_REF_QUEUED
73// skipped private _Py_REF_MERGED
74
75// skipped private _Py_REF_SHARED
76
77#[repr(C)]
78#[derive(Copy, Clone)]
79#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
80/// This union is anonymous in CPython, so the name was given by PyO3 because
81/// Rust unions need a name.
82pub union PyObjectObRefcnt {
83 pub ob_refcnt: Py_ssize_t,
84 #[cfg(target_pointer_width = "64")]
85 pub ob_refcnt_split: [crate::PY_UINT32_T; 2],
86}
87
88#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
89impl std::fmt::Debug for PyObjectObRefcnt {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 write!(f, "{}", unsafe { self.ob_refcnt })
92 }
93}
94
95#[cfg(all(not(Py_3_12), not(Py_GIL_DISABLED)))]
96pub type PyObjectObRefcnt = Py_ssize_t;
97
98#[repr(C)]
99#[derive(Debug)]
100pub struct PyObject {
101 #[cfg(py_sys_config = "Py_TRACE_REFS")]
102 pub _ob_next: *mut PyObject,
103 #[cfg(py_sys_config = "Py_TRACE_REFS")]
104 pub _ob_prev: *mut PyObject,
105 #[cfg(Py_GIL_DISABLED)]
106 pub ob_tid: libc::uintptr_t,
107 #[cfg(Py_GIL_DISABLED)]
108 pub _padding: 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
124// skipped private _PyObject_CAST
125
126#[repr(C)]
127#[derive(Debug)]
128pub struct PyVarObject {
129 pub ob_base: PyObject,
130 #[cfg(not(GraalPy))]
131 pub ob_size: Py_ssize_t,
132 // On GraalPy the field is physically there, but not always populated. We hide it to prevent accidental misuse
133 #[cfg(GraalPy)]
134 pub _ob_size_graalpy: Py_ssize_t,
135}
136
137// skipped private _PyVarObject_CAST
138
139#[inline]
140#[cfg(not(all(PyPy, Py_3_10)))]
141#[cfg_attr(docsrs, doc(cfg(all())))]
142pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int {
143 (x == y).into()
144}
145
146#[cfg(all(PyPy, Py_3_10))]
147#[cfg_attr(docsrs, doc(cfg(all())))]
148extern "C" {
149 #[cfg_attr(PyPy, link_name = "PyPy_Is")]
150 pub fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int;
151}
152
153// skipped private _Py_GetThreadLocal_Addr
154
155// skipped private _Py_ThreadId
156
157// skipped private _Py_IsOwnedByCurrentThread
158
159#[inline]
160pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
161 #[cfg(Py_GIL_DISABLED)]
162 {
163 let local = (*ob).ob_ref_local.load(Relaxed);
164 if local == _Py_IMMORTAL_REFCNT_LOCAL {
165 return _Py_IMMORTAL_REFCNT;
166 }
167 let shared = (*ob).ob_ref_shared.load(Relaxed);
168 local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
169 }
170
171 #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
172 {
173 (*ob).ob_refcnt.ob_refcnt
174 }
175
176 #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]
177 {
178 (*ob).ob_refcnt
179 }
180
181 #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]
182 {
183 _Py_REFCNT(ob)
184 }
185}
186
187#[inline]
188pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
189 #[cfg(not(GraalPy))]
190 return (*ob).ob_type;
191 #[cfg(GraalPy)]
192 return _Py_TYPE(ob);
193}
194
195#[cfg_attr(windows, link(name = "pythonXY"))]
196unsafeextern "C" {
197 #[cfg_attr(PyPy, link_name = "PyPyLong_Type")]
198 pub unsafestatic mut PyLong_Type: PyTypeObject;
199 #[cfg_attr(PyPy, link_name = "PyPyBool_Type")]
200 pub unsafestatic mut PyBool_Type: PyTypeObject;
201}
202
203#[inline]
204pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {
205 #[cfg(not(GraalPy))]
206 {
207 debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyLong_Type));
208 debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyBool_Type));
209 (*ob.cast::<PyVarObject>()).ob_size
210 }
211 #[cfg(GraalPy)]
212 _Py_SIZE(ob)
213}
214
215#[inline(always)]
216#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]
217unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
218 #[cfg(target_pointer_width = "64")]
219 {
220 (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
221 }
222
223 #[cfg(target_pointer_width = "32")]
224 {
225 ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
226 }
227}
228
229#[inline]
230pub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
231 (Py_TYPE(ob) == tp) as c_int
232}
233
234// skipped _Py_SetRefCnt
235
236// skipped Py_SET_REFCNT
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;
279
280#[cfg(Py_3_8)]
281pub type vectorcallfunc = unsafe extern "C" fn(
282 callable: *mut PyObject,
283 args: *const *mut PyObject,
284 nargsf: libc::size_t,
285 kwnames: *mut PyObject,
286) -> *mut PyObject;
287
288#[repr(C)]
289#[derive(Copy, Clone)]
290pub struct PyType_Slot {
291 pub slot: c_int,
292 pub pfunc: *mut c_void,
293}
294
295impl Default for PyType_Slot {
296 fn default() -> PyType_Slot {
297 unsafe { mem::zeroed() }
298 }
299}
300
301#[repr(C)]
302#[derive(Copy, Clone)]
303pub struct PyType_Spec {
304 pub name: *const c_char,
305 pub basicsize: c_int,
306 pub itemsize: c_int,
307 pub flags: c_uint,
308 pub slots: *mut PyType_Slot,
309}
310
311impl Default for PyType_Spec {
312 fn default() -> PyType_Spec {
313 unsafe { mem::zeroed() }
314 }
315}
316
317unsafeextern "C" {
318 #[cfg_attr(PyPy, link_name = "PyPyType_FromSpec")]
319 pub unsafefn PyType_FromSpec(arg1: *mut PyType_Spec) -> *mut PyObject;
320
321 #[cfg_attr(PyPy, link_name = "PyPyType_FromSpecWithBases")]
322 pub unsafefn PyType_FromSpecWithBases(arg1: *mut PyType_Spec, arg2: *mut PyObject) -> *mut PyObject;
323
324 #[cfg_attr(PyPy, link_name = "PyPyType_GetSlot")]
325 pub unsafefn PyType_GetSlot(arg1: *mut PyTypeObject, arg2: c_int) -> *mut c_void;
326
327 #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
328 #[cfg_attr(PyPy, link_name = "PyPyType_FromModuleAndSpec")]
329 pub unsafefn PyType_FromModuleAndSpec(
330 module: *mut PyObject,
331 spec: *mut PyType_Spec,
332 bases: *mut PyObject,
333 ) -> *mut PyObject;
334
335 #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
336 #[cfg_attr(PyPy, link_name = "PyPyType_GetModule")]
337 pub unsafefn PyType_GetModule(arg1: *mut PyTypeObject) -> *mut PyObject;
338
339 #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
340 #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleState")]
341 pub unsafefn PyType_GetModuleState(arg1: *mut PyTypeObject) -> *mut c_void;
342
343 #[cfg(Py_3_11)]
344 #[cfg_attr(PyPy, link_name = "PyPyType_GetName")]
345 pub fn PyType_GetName(arg1: *mut PyTypeObject) -> *mut PyObject;
346
347 #[cfg(Py_3_11)]
348 #[cfg_attr(PyPy, link_name = "PyPyType_GetQualName")]
349 pub fn PyType_GetQualName(arg1: *mut PyTypeObject) -> *mut PyObject;
350
351 #[cfg(Py_3_13)]
352 #[cfg_attr(PyPy, link_name = "PyPyType_GetFullyQualifiedName")]
353 pub fn PyType_GetFullyQualifiedName(arg1: *mut PyTypeObject) -> *mut PyObject;
354
355 #[cfg(Py_3_13)]
356 #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleName")]
357 pub fn PyType_GetModuleName(arg1: *mut PyTypeObject) -> *mut PyObject;
358
359 #[cfg(Py_3_12)]
360 #[cfg_attr(PyPy, link_name = "PyPyType_FromMetaclass")]
361 pub fn PyType_FromMetaclass(
362 metaclass: *mut PyTypeObject,
363 module: *mut PyObject,
364 spec: *mut PyType_Spec,
365 bases: *mut PyObject,
366 ) -> *mut PyObject;
367
368 #[cfg(Py_3_12)]
369 #[cfg_attr(PyPy, link_name = "PyPyObject_GetTypeData")]
370 pub fn PyObject_GetTypeData(obj: *mut PyObject, cls: *mut PyTypeObject) -> *mut c_void;
371
372 #[cfg(Py_3_12)]
373 #[cfg_attr(PyPy, link_name = "PyPyObject_GetTypeDataSize")]
374 pub fn PyObject_GetTypeDataSize(cls: *mut PyTypeObject) -> Py_ssize_t;
375
376 #[cfg_attr(PyPy, link_name = "PyPyType_IsSubtype")]
377 pub unsafefn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int;
378}
379
380#[inline]
381pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
382 (Py_IS_TYPE(ob, tp) != 0 || PyType_IsSubtype(a:Py_TYPE(ob), b:tp) != 0) as c_int
383}
384
385#[cfg_attr(windows, link(name = "pythonXY"))]
386unsafeextern "C" {
387 /// built-in 'type'
388 #[cfg_attr(PyPy, link_name = "PyPyType_Type")]
389 pub unsafestatic mut PyType_Type: PyTypeObject;
390 /// built-in 'object'
391 #[cfg_attr(PyPy, link_name = "PyPyBaseObject_Type")]
392 pub unsafestatic mut PyBaseObject_Type: PyTypeObject;
393 /// built-in 'super'
394 pub unsafestatic mut PySuper_Type: PyTypeObject;
395}
396
397unsafeextern "C" {
398 pub unsafefn PyType_GetFlags(arg1: *mut PyTypeObject) -> c_ulong;
399
400 #[cfg_attr(PyPy, link_name = "PyPyType_Ready")]
401 pub unsafefn PyType_Ready(t: *mut PyTypeObject) -> c_int;
402 #[cfg_attr(PyPy, link_name = "PyPyType_GenericAlloc")]
403 pub unsafefn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject;
404 #[cfg_attr(PyPy, link_name = "PyPyType_GenericNew")]
405 pub unsafefn PyType_GenericNew(
406 t: *mut PyTypeObject,
407 args: *mut PyObject,
408 kwds: *mut PyObject,
409 ) -> *mut PyObject;
410 pub unsafefn PyType_ClearCache() -> c_uint;
411 #[cfg_attr(PyPy, link_name = "PyPyType_Modified")]
412 pub unsafefn PyType_Modified(t: *mut PyTypeObject);
413
414 #[cfg_attr(PyPy, link_name = "PyPyObject_Repr")]
415 pub unsafefn PyObject_Repr(o: *mut PyObject) -> *mut PyObject;
416 #[cfg_attr(PyPy, link_name = "PyPyObject_Str")]
417 pub unsafefn PyObject_Str(o: *mut PyObject) -> *mut PyObject;
418 #[cfg_attr(PyPy, link_name = "PyPyObject_ASCII")]
419 pub unsafefn PyObject_ASCII(arg1: *mut PyObject) -> *mut PyObject;
420 #[cfg_attr(PyPy, link_name = "PyPyObject_Bytes")]
421 pub unsafefn PyObject_Bytes(arg1: *mut PyObject) -> *mut PyObject;
422 #[cfg_attr(PyPy, link_name = "PyPyObject_RichCompare")]
423 pub unsafefn PyObject_RichCompare(
424 arg1: *mut PyObject,
425 arg2: *mut PyObject,
426 arg3: c_int,
427 ) -> *mut PyObject;
428 #[cfg_attr(PyPy, link_name = "PyPyObject_RichCompareBool")]
429 pub unsafefn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int)
430 -> c_int;
431 #[cfg_attr(PyPy, link_name = "PyPyObject_GetAttrString")]
432 pub unsafefn PyObject_GetAttrString(arg1: *mut PyObject, arg2: *const c_char) -> *mut PyObject;
433 #[cfg_attr(PyPy, link_name = "PyPyObject_SetAttrString")]
434 pub unsafefn PyObject_SetAttrString(
435 arg1: *mut PyObject,
436 arg2: *const c_char,
437 arg3: *mut PyObject,
438 ) -> c_int;
439 #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h
440 #[cfg_attr(PyPy, link_name = "PyPyObject_DelAttrString")]
441 pub fn PyObject_DelAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
442 #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrString")]
443 pub unsafefn PyObject_HasAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
444 #[cfg_attr(PyPy, link_name = "PyPyObject_GetAttr")]
445 pub unsafefn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
446 #[cfg(Py_3_13)]
447 #[cfg_attr(PyPy, link_name = "PyPyObject_GetOptionalAttr")]
448 pub fn PyObject_GetOptionalAttr(
449 arg1: *mut PyObject,
450 arg2: *mut PyObject,
451 arg3: *mut *mut PyObject,
452 ) -> c_int;
453 #[cfg(Py_3_13)]
454 #[cfg_attr(PyPy, link_name = "PyPyObject_GetOptionalAttrString")]
455 pub fn PyObject_GetOptionalAttrString(
456 arg1: *mut PyObject,
457 arg2: *const c_char,
458 arg3: *mut *mut PyObject,
459 ) -> c_int;
460 #[cfg_attr(PyPy, link_name = "PyPyObject_SetAttr")]
461 pub unsafefn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject)
462 -> c_int;
463 #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h
464 #[cfg_attr(PyPy, link_name = "PyPyObject_DelAttr")]
465 pub fn PyObject_DelAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
466 #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttr")]
467 pub unsafefn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
468 #[cfg(Py_3_13)]
469 #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrWithError")]
470 pub fn PyObject_HasAttrWithError(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
471 #[cfg(Py_3_13)]
472 #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrStringWithError")]
473 pub fn PyObject_HasAttrStringWithError(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
474 #[cfg_attr(PyPy, link_name = "PyPyObject_SelfIter")]
475 pub unsafefn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject;
476 #[cfg_attr(PyPy, link_name = "PyPyObject_GenericGetAttr")]
477 pub unsafefn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
478 #[cfg_attr(PyPy, link_name = "PyPyObject_GenericSetAttr")]
479 pub unsafefn PyObject_GenericSetAttr(
480 arg1: *mut PyObject,
481 arg2: *mut PyObject,
482 arg3: *mut PyObject,
483 ) -> c_int;
484 #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))]
485 #[cfg_attr(PyPy, link_name = "PyPyObject_GenericGetDict")]
486 pub unsafefn PyObject_GenericGetDict(arg1: *mut PyObject, arg2: *mut c_void) -> *mut PyObject;
487 #[cfg_attr(PyPy, link_name = "PyPyObject_GenericSetDict")]
488 pub unsafefn PyObject_GenericSetDict(
489 arg1: *mut PyObject,
490 arg2: *mut PyObject,
491 arg3: *mut c_void,
492 ) -> c_int;
493 #[cfg_attr(PyPy, link_name = "PyPyObject_Hash")]
494 pub unsafefn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t;
495 #[cfg_attr(PyPy, link_name = "PyPyObject_HashNotImplemented")]
496 pub unsafefn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t;
497 #[cfg_attr(PyPy, link_name = "PyPyObject_IsTrue")]
498 pub unsafefn PyObject_IsTrue(arg1: *mut PyObject) -> c_int;
499 #[cfg_attr(PyPy, link_name = "PyPyObject_Not")]
500 pub unsafefn PyObject_Not(arg1: *mut PyObject) -> c_int;
501 #[cfg_attr(PyPy, link_name = "PyPyCallable_Check")]
502 pub unsafefn PyCallable_Check(arg1: *mut PyObject) -> c_int;
503 #[cfg_attr(PyPy, link_name = "PyPyObject_ClearWeakRefs")]
504 pub unsafefn PyObject_ClearWeakRefs(arg1: *mut PyObject);
505
506 #[cfg_attr(PyPy, link_name = "PyPyObject_Dir")]
507 pub unsafefn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject;
508 pub unsafefn Py_ReprEnter(arg1: *mut PyObject) -> c_int;
509 pub unsafefn Py_ReprLeave(arg1: *mut PyObject);
510}
511
512// Flag bits for printing:
513pub const Py_PRINT_RAW: c_int = 1; // No string quotes etc.
514
515// skipped because is a private API
516// const _Py_TPFLAGS_STATIC_BUILTIN: c_ulong = 1 << 1;
517
518#[cfg(all(Py_3_12, not(Py_LIMITED_API)))]
519pub const Py_TPFLAGS_MANAGED_WEAKREF: c_ulong = 1 << 3;
520
521#[cfg(all(Py_3_11, not(Py_LIMITED_API)))]
522pub const Py_TPFLAGS_MANAGED_DICT: c_ulong = 1 << 4;
523
524#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
525pub const Py_TPFLAGS_SEQUENCE: c_ulong = 1 << 5;
526
527#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]
528pub const Py_TPFLAGS_MAPPING: c_ulong = 1 << 6;
529
530#[cfg(Py_3_10)]
531pub const Py_TPFLAGS_DISALLOW_INSTANTIATION: c_ulong = 1 << 7;
532
533#[cfg(Py_3_10)]
534pub const Py_TPFLAGS_IMMUTABLETYPE: c_ulong = 1 << 8;
535
536/// Set if the type object is dynamically allocated
537pub const Py_TPFLAGS_HEAPTYPE: c_ulong = 1 << 9;
538
539/// Set if the type allows subclassing
540pub const Py_TPFLAGS_BASETYPE: c_ulong = 1 << 10;
541
542/// Set if the type implements the vectorcall protocol (PEP 590)
543#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]
544pub const Py_TPFLAGS_HAVE_VECTORCALL: c_ulong = 1 << 11;
545// skipped backwards-compatibility alias _Py_TPFLAGS_HAVE_VECTORCALL
546
547/// Set if the type is 'ready' -- fully initialized
548pub const Py_TPFLAGS_READY: c_ulong = 1 << 12;
549
550/// Set while the type is being 'readied', to prevent recursive ready calls
551pub const Py_TPFLAGS_READYING: c_ulong = 1 << 13;
552
553/// Objects support garbage collection (see objimp.h)
554pub const Py_TPFLAGS_HAVE_GC: c_ulong = 1 << 14;
555
556const Py_TPFLAGS_HAVE_STACKLESS_EXTENSION: c_ulong = 0;
557
558#[cfg(Py_3_8)]
559pub const Py_TPFLAGS_METHOD_DESCRIPTOR: c_ulong = 1 << 17;
560
561pub const Py_TPFLAGS_VALID_VERSION_TAG: c_ulong = 1 << 19;
562
563/* Type is abstract and cannot be instantiated */
564pub const Py_TPFLAGS_IS_ABSTRACT: c_ulong = 1 << 20;
565
566// skipped non-limited / 3.10 Py_TPFLAGS_HAVE_AM_SEND
567#[cfg(Py_3_12)]
568pub const Py_TPFLAGS_ITEMS_AT_END: c_ulong = 1 << 23;
569
570/* These flags are used to determine if a type is a subclass. */
571pub const Py_TPFLAGS_LONG_SUBCLASS: c_ulong = 1 << 24;
572pub const Py_TPFLAGS_LIST_SUBCLASS: c_ulong = 1 << 25;
573pub const Py_TPFLAGS_TUPLE_SUBCLASS: c_ulong = 1 << 26;
574pub const Py_TPFLAGS_BYTES_SUBCLASS: c_ulong = 1 << 27;
575pub const Py_TPFLAGS_UNICODE_SUBCLASS: c_ulong = 1 << 28;
576pub const Py_TPFLAGS_DICT_SUBCLASS: c_ulong = 1 << 29;
577pub const Py_TPFLAGS_BASE_EXC_SUBCLASS: c_ulong = 1 << 30;
578pub const Py_TPFLAGS_TYPE_SUBCLASS: c_ulong = 1 << 31;
579
580pub const Py_TPFLAGS_DEFAULT: c_ulong = if cfg!(Py_3_10) {
581 Py_TPFLAGS_HAVE_STACKLESS_EXTENSION
582} else {
583 Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | Py_TPFLAGS_HAVE_VERSION_TAG
584};
585
586pub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1;
587pub const Py_TPFLAGS_HAVE_VERSION_TAG: c_ulong = 1 << 18;
588
589unsafeextern "C" {
590 #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
591 fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
592 #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
593 fn _Py_INCREF_IncRefTotal();
594 #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
595 fn _Py_DECREF_DecRefTotal();
596
597 #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
598 unsafefn _Py_Dealloc(arg1: *mut PyObject);
599
600 #[cfg_attr(PyPy, link_name = "PyPy_IncRef")]
601 #[cfg_attr(GraalPy, link_name = "_Py_IncRef")]
602 pub unsafefn Py_IncRef(o: *mut PyObject);
603 #[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
604 #[cfg_attr(GraalPy, link_name = "_Py_DecRef")]
605 pub unsafefn Py_DecRef(o: *mut PyObject);
606
607 #[cfg(all(Py_3_10, not(PyPy)))]
608 unsafefn _Py_IncRef(o: *mut PyObject);
609 #[cfg(all(Py_3_10, not(PyPy)))]
610 unsafefn _Py_DecRef(o: *mut PyObject);
611
612 #[cfg(GraalPy)]
613 fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;
614
615 #[cfg(GraalPy)]
616 fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject;
617
618 #[cfg(GraalPy)]
619 fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t;
620}
621
622#[inline(always)]
623pub unsafe fn Py_INCREF(op: *mut PyObject) {
624 // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
625 // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
626 #[cfg(any(
627 Py_GIL_DISABLED,
628 Py_LIMITED_API,
629 py_sys_config = "Py_REF_DEBUG",
630 GraalPy
631 ))]
632 {
633 // _Py_IncRef was added to the ABI in 3.10; skips null checks
634 #[cfg(all(Py_3_10, not(PyPy)))]
635 {
636 _Py_IncRef(op);
637 }
638
639 #[cfg(any(not(Py_3_10), PyPy))]
640 {
641 Py_IncRef(op);
642 }
643 }
644
645 // version-specific builds are allowed to directly manipulate the reference count
646 #[cfg(not(any(
647 Py_GIL_DISABLED,
648 Py_LIMITED_API,
649 py_sys_config = "Py_REF_DEBUG",
650 GraalPy
651 )))]
652 {
653 #[cfg(all(Py_3_12, target_pointer_width = "64"))]
654 {
655 let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
656 let new_refcnt = cur_refcnt.wrapping_add(1);
657 if new_refcnt == 0 {
658 return;
659 }
660 (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
661 }
662
663 #[cfg(all(Py_3_12, target_pointer_width = "32"))]
664 {
665 if _Py_IsImmortal(op) != 0 {
666 return;
667 }
668 (*op).ob_refcnt.ob_refcnt += 1
669 }
670
671 #[cfg(not(Py_3_12))]
672 {
673 (*op).ob_refcnt += 1
674 }
675
676 // Skipped _Py_INCREF_STAT_INC - if anyone wants this, please file an issue
677 // or submit a PR supporting Py_STATS build option and pystats.h
678 }
679}
680
681#[inline(always)]
682#[cfg_attr(
683 all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
684 track_caller
685)]
686pub unsafe fn Py_DECREF(op: *mut PyObject) {
687 // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting
688 // On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts
689 // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.
690 #[cfg(any(
691 Py_GIL_DISABLED,
692 Py_LIMITED_API,
693 all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
694 GraalPy
695 ))]
696 {
697 // _Py_DecRef was added to the ABI in 3.10; skips null checks
698 #[cfg(all(Py_3_10, not(PyPy)))]
699 {
700 _Py_DecRef(op);
701 }
702
703 #[cfg(any(not(Py_3_10), PyPy))]
704 {
705 Py_DecRef(op);
706 }
707 }
708
709 #[cfg(not(any(
710 Py_GIL_DISABLED,
711 Py_LIMITED_API,
712 all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
713 GraalPy
714 )))]
715 {
716 #[cfg(Py_3_12)]
717 if _Py_IsImmortal(op) != 0 {
718 return;
719 }
720
721 // Skipped _Py_DECREF_STAT_INC - if anyone needs this, please file an issue
722 // or submit a PR supporting Py_STATS build option and pystats.h
723
724 #[cfg(py_sys_config = "Py_REF_DEBUG")]
725 _Py_DECREF_DecRefTotal();
726
727 #[cfg(Py_3_12)]
728 {
729 (*op).ob_refcnt.ob_refcnt -= 1;
730
731 #[cfg(py_sys_config = "Py_REF_DEBUG")]
732 if (*op).ob_refcnt.ob_refcnt < 0 {
733 let location = std::panic::Location::caller();
734 let filename = std::ffi::CString::new(location.file()).unwrap();
735 _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
736 }
737
738 if (*op).ob_refcnt.ob_refcnt == 0 {
739 _Py_Dealloc(op);
740 }
741 }
742
743 #[cfg(not(Py_3_12))]
744 {
745 (*op).ob_refcnt -= 1;
746
747 if (*op).ob_refcnt == 0 {
748 _Py_Dealloc(op);
749 }
750 }
751 }
752}
753
754#[inline]
755pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
756 let tmp: *mut PyObject = *op;
757 if !tmp.is_null() {
758 *op = ptr::null_mut();
759 Py_DECREF(op:tmp);
760 }
761}
762
763#[inline]
764pub unsafe fn Py_XINCREF(op: *mut PyObject) {
765 if !op.is_null() {
766 Py_INCREF(op)
767 }
768}
769
770#[inline]
771pub unsafe fn Py_XDECREF(op: *mut PyObject) {
772 if !op.is_null() {
773 Py_DECREF(op)
774 }
775}
776
777unsafeextern "C" {
778 #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
779 #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
780 pub unsafefn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
781 #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
782 #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
783 pub unsafefn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
784}
785
786// macro _Py_NewRef not public; reimplemented directly inside Py_NewRef here
787// macro _Py_XNewRef not public; reimplemented directly inside Py_XNewRef here
788
789#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
790#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
791#[inline]
792pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
793 Py_INCREF(obj);
794 obj
795}
796
797#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
798#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
799#[inline]
800pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
801 Py_XINCREF(obj);
802 obj
803}
804
805#[cfg(Py_3_13)]
806pub const Py_CONSTANT_NONE: c_uint = 0;
807#[cfg(Py_3_13)]
808pub const Py_CONSTANT_FALSE: c_uint = 1;
809#[cfg(Py_3_13)]
810pub const Py_CONSTANT_TRUE: c_uint = 2;
811#[cfg(Py_3_13)]
812pub const Py_CONSTANT_ELLIPSIS: c_uint = 3;
813#[cfg(Py_3_13)]
814pub const Py_CONSTANT_NOT_IMPLEMENTED: c_uint = 4;
815#[cfg(Py_3_13)]
816pub const Py_CONSTANT_ZERO: c_uint = 5;
817#[cfg(Py_3_13)]
818pub const Py_CONSTANT_ONE: c_uint = 6;
819#[cfg(Py_3_13)]
820pub const Py_CONSTANT_EMPTY_STR: c_uint = 7;
821#[cfg(Py_3_13)]
822pub const Py_CONSTANT_EMPTY_BYTES: c_uint = 8;
823#[cfg(Py_3_13)]
824pub const Py_CONSTANT_EMPTY_TUPLE: c_uint = 9;
825
826unsafeextern "C" {
827 #[cfg(Py_3_13)]
828 #[cfg_attr(PyPy, link_name = "PyPy_GetConstant")]
829 pub fn Py_GetConstant(constant_id: c_uint) -> *mut PyObject;
830 #[cfg(Py_3_13)]
831 #[cfg_attr(PyPy, link_name = "PyPy_GetConstantBorrowed")]
832 pub fn Py_GetConstantBorrowed(constant_id: c_uint) -> *mut PyObject;
833}
834
835#[cfg_attr(windows, link(name = "pythonXY"))]
836unsafeextern "C" {
837 #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
838 #[cfg_attr(PyPy, link_name = "_PyPy_NoneStruct")]
839 unsafestatic mut _Py_NoneStruct: PyObject;
840
841 #[cfg(GraalPy)]
842 static mut _Py_NoneStructReference: *mut PyObject;
843}
844
845#[inline]
846pub unsafe fn Py_None() -> *mut PyObject {
847 #[cfg(all(not(GraalPy), all(Py_3_13, Py_LIMITED_API)))]
848 return Py_GetConstantBorrowed(Py_CONSTANT_NONE);
849
850 #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
851 return ptr::addr_of_mut!(_Py_NoneStruct);
852
853 #[cfg(GraalPy)]
854 return _Py_NoneStructReference;
855}
856
857#[inline]
858pub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int {
859 Py_Is(x, y:Py_None())
860}
861
862// skipped Py_RETURN_NONE
863
864#[cfg_attr(windows, link(name = "pythonXY"))]
865unsafeextern "C" {
866 #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
867 #[cfg_attr(PyPy, link_name = "_PyPy_NotImplementedStruct")]
868 unsafestatic mut _Py_NotImplementedStruct: PyObject;
869
870 #[cfg(GraalPy)]
871 static mut _Py_NotImplementedStructReference: *mut PyObject;
872}
873
874#[inline]
875pub unsafe fn Py_NotImplemented() -> *mut PyObject {
876 #[cfg(all(not(GraalPy), all(Py_3_13, Py_LIMITED_API)))]
877 return Py_GetConstantBorrowed(Py_CONSTANT_NOT_IMPLEMENTED);
878
879 #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]
880 return ptr::addr_of_mut!(_Py_NotImplementedStruct);
881
882 #[cfg(GraalPy)]
883 return _Py_NotImplementedStructReference;
884}
885
886// skipped Py_RETURN_NOTIMPLEMENTED
887
888/* Rich comparison opcodes */
889pub const Py_LT: c_int = 0;
890pub const Py_LE: c_int = 1;
891pub const Py_EQ: c_int = 2;
892pub const Py_NE: c_int = 3;
893pub const Py_GT: c_int = 4;
894pub const Py_GE: c_int = 5;
895
896#[cfg(Py_3_10)]
897#[repr(C)]
898#[derive(Copy, Clone, Debug, PartialEq, Eq)]
899pub enum PySendResult {
900 PYGEN_RETURN = 0,
901 PYGEN_ERROR = -1,
902 PYGEN_NEXT = 1,
903}
904
905// skipped Py_RETURN_RICHCOMPARE
906
907#[inline]
908pub unsafe fn PyType_HasFeature(ty: *mut PyTypeObject, feature: c_ulong) -> c_int {
909 #[cfg(Py_LIMITED_API)]
910 let flags = PyType_GetFlags(arg1:ty);
911
912 #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
913 let flags = (*ty).tp_flags.load(std::sync::atomic::Ordering::Relaxed);
914
915 #[cfg(all(not(Py_LIMITED_API), not(Py_GIL_DISABLED)))]
916 let flags = (*ty).tp_flags;
917
918 ((flags & feature) != 0) as c_int
919}
920
921#[inline]
922pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int {
923 PyType_HasFeature(ty:t, feature:f)
924}
925
926#[inline]
927pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
928 PyType_FastSubclass(t:Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS)
929}
930
931// skipped _PyType_CAST
932
933#[inline]
934pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {
935 Py_IS_TYPE(ob:op, tp:ptr::addr_of_mut!(PyType_Type))
936}
937
938unsafeextern "C" {
939 #[cfg(any(Py_3_13, all(Py_3_11, not(Py_LIMITED_API))))]
940 #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleByDef")]
941 pub fn PyType_GetModuleByDef(
942 arg1: *mut crate::PyTypeObject,
943 arg2: *mut crate::PyModuleDef,
944 ) -> *mut PyObject;
945}
946