Skip to main content

pyo3_ffi/cpython/
object.rs

1use crate::vectorcallfunc;
2use crate::{object, PyGetSetDef, PyMemberDef, PyMethodDef, PyObject, Py_ssize_t};
3use std::ffi::{c_char, c_int, c_uint, c_void};
4use std::mem;
5
6// skipped private _Py_NewReference
7// skipped private _Py_NewReferenceNoTotal
8// skipped private _Py_ResurrectReference
9
10// skipped private _Py_GetGlobalRefTotal
11// skipped private _Py_GetRefTotal
12// skipped private _Py_GetLegacyRefTotal
13// skipped private _PyInterpreterState_GetRefTotal
14
15// skipped private _Py_Identifier
16
17// skipped private _Py_static_string_init
18// skipped private _Py_static_string
19// skipped private _Py_IDENTIFIER
20
21#[cfg(not(Py_3_11))] // moved to src/buffer.rs from Python
22mod bufferinfo {
23    use crate::Py_ssize_t;
24    use std::ffi::{c_char, c_int, c_void};
25    use std::ptr;
26
27    #[repr(C)]
28    #[derive(Copy, Clone)]
29    pub struct Py_buffer {
30        pub buf: *mut c_void,
31        /// Owned reference
32        pub obj: *mut crate::PyObject,
33        pub len: Py_ssize_t,
34        pub itemsize: Py_ssize_t,
35        pub readonly: c_int,
36        pub ndim: c_int,
37        pub format: *mut c_char,
38        pub shape: *mut Py_ssize_t,
39        pub strides: *mut Py_ssize_t,
40        pub suboffsets: *mut Py_ssize_t,
41        pub internal: *mut c_void,
42        #[cfg(PyPy)]
43        pub flags: c_int,
44        #[cfg(PyPy)]
45        pub _strides: [Py_ssize_t; PyBUF_MAX_NDIM as usize],
46        #[cfg(PyPy)]
47        pub _shape: [Py_ssize_t; PyBUF_MAX_NDIM as usize],
48    }
49
50    impl Py_buffer {
51        #[allow(clippy::new_without_default)]
52        pub const fn new() -> Self {
53            Py_buffer {
54                buf: ptr::null_mut(),
55                obj: ptr::null_mut(),
56                len: 0,
57                itemsize: 0,
58                readonly: 0,
59                ndim: 0,
60                format: ptr::null_mut(),
61                shape: ptr::null_mut(),
62                strides: ptr::null_mut(),
63                suboffsets: ptr::null_mut(),
64                internal: ptr::null_mut(),
65                #[cfg(PyPy)]
66                flags: 0,
67                #[cfg(PyPy)]
68                _strides: [0; PyBUF_MAX_NDIM as usize],
69                #[cfg(PyPy)]
70                _shape: [0; PyBUF_MAX_NDIM as usize],
71            }
72        }
73    }
74
75    pub type getbufferproc = unsafe extern "C" fn(
76        arg1: *mut crate::PyObject,
77        arg2: *mut Py_buffer,
78        arg3: c_int,
79    ) -> c_int;
80    pub type releasebufferproc =
81        unsafe extern "C" fn(arg1: *mut crate::PyObject, arg2: *mut Py_buffer);
82
83    /// Maximum number of dimensions
84    pub const PyBUF_MAX_NDIM: c_int = if cfg!(PyPy) { 36 } else { 64 };
85
86    /* Flags for getting buffers */
87    pub const PyBUF_SIMPLE: c_int = 0;
88    pub const PyBUF_WRITABLE: c_int = 0x0001;
89    /* we used to include an E, backwards compatible alias */
90    pub const PyBUF_WRITEABLE: c_int = PyBUF_WRITABLE;
91    pub const PyBUF_FORMAT: c_int = 0x0004;
92    pub const PyBUF_ND: c_int = 0x0008;
93    pub const PyBUF_STRIDES: c_int = 0x0010 | PyBUF_ND;
94    pub const PyBUF_C_CONTIGUOUS: c_int = 0x0020 | PyBUF_STRIDES;
95    pub const PyBUF_F_CONTIGUOUS: c_int = 0x0040 | PyBUF_STRIDES;
96    pub const PyBUF_ANY_CONTIGUOUS: c_int = 0x0080 | PyBUF_STRIDES;
97    pub const PyBUF_INDIRECT: c_int = 0x0100 | PyBUF_STRIDES;
98
99    pub const PyBUF_CONTIG: c_int = PyBUF_ND | PyBUF_WRITABLE;
100    pub const PyBUF_CONTIG_RO: c_int = PyBUF_ND;
101
102    pub const PyBUF_STRIDED: c_int = PyBUF_STRIDES | PyBUF_WRITABLE;
103    pub const PyBUF_STRIDED_RO: c_int = PyBUF_STRIDES;
104
105    pub const PyBUF_RECORDS: c_int = PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT;
106    pub const PyBUF_RECORDS_RO: c_int = PyBUF_STRIDES | PyBUF_FORMAT;
107
108    pub const PyBUF_FULL: c_int = PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT;
109    pub const PyBUF_FULL_RO: c_int = PyBUF_INDIRECT | PyBUF_FORMAT;
110
111    pub const PyBUF_READ: c_int = 0x100;
112    pub const PyBUF_WRITE: c_int = 0x200;
113}
114
115#[cfg(not(Py_3_11))]
116pub use self::bufferinfo::*;
117
118#[repr(C)]
119#[derive(Copy, Clone)]
120pub struct PyNumberMethods {
121    pub nb_add: Option<object::binaryfunc>,
122    pub nb_subtract: Option<object::binaryfunc>,
123    pub nb_multiply: Option<object::binaryfunc>,
124    pub nb_remainder: Option<object::binaryfunc>,
125    pub nb_divmod: Option<object::binaryfunc>,
126    pub nb_power: Option<object::ternaryfunc>,
127    pub nb_negative: Option<object::unaryfunc>,
128    pub nb_positive: Option<object::unaryfunc>,
129    pub nb_absolute: Option<object::unaryfunc>,
130    pub nb_bool: Option<object::inquiry>,
131    pub nb_invert: Option<object::unaryfunc>,
132    pub nb_lshift: Option<object::binaryfunc>,
133    pub nb_rshift: Option<object::binaryfunc>,
134    pub nb_and: Option<object::binaryfunc>,
135    pub nb_xor: Option<object::binaryfunc>,
136    pub nb_or: Option<object::binaryfunc>,
137    pub nb_int: Option<object::unaryfunc>,
138    pub nb_reserved: *mut c_void,
139    pub nb_float: Option<object::unaryfunc>,
140    pub nb_inplace_add: Option<object::binaryfunc>,
141    pub nb_inplace_subtract: Option<object::binaryfunc>,
142    pub nb_inplace_multiply: Option<object::binaryfunc>,
143    pub nb_inplace_remainder: Option<object::binaryfunc>,
144    pub nb_inplace_power: Option<object::ternaryfunc>,
145    pub nb_inplace_lshift: Option<object::binaryfunc>,
146    pub nb_inplace_rshift: Option<object::binaryfunc>,
147    pub nb_inplace_and: Option<object::binaryfunc>,
148    pub nb_inplace_xor: Option<object::binaryfunc>,
149    pub nb_inplace_or: Option<object::binaryfunc>,
150    pub nb_floor_divide: Option<object::binaryfunc>,
151    pub nb_true_divide: Option<object::binaryfunc>,
152    pub nb_inplace_floor_divide: Option<object::binaryfunc>,
153    pub nb_inplace_true_divide: Option<object::binaryfunc>,
154    pub nb_index: Option<object::unaryfunc>,
155    pub nb_matrix_multiply: Option<object::binaryfunc>,
156    pub nb_inplace_matrix_multiply: Option<object::binaryfunc>,
157}
158
159#[repr(C)]
160#[derive(Clone)]
161pub struct PySequenceMethods {
162    pub sq_length: Option<object::lenfunc>,
163    pub sq_concat: Option<object::binaryfunc>,
164    pub sq_repeat: Option<object::ssizeargfunc>,
165    pub sq_item: Option<object::ssizeargfunc>,
166    pub was_sq_slice: *mut c_void,
167    pub sq_ass_item: Option<object::ssizeobjargproc>,
168    pub was_sq_ass_slice: *mut c_void,
169    pub sq_contains: Option<object::objobjproc>,
170    pub sq_inplace_concat: Option<object::binaryfunc>,
171    pub sq_inplace_repeat: Option<object::ssizeargfunc>,
172}
173
174#[repr(C)]
175#[derive(Clone, Default)]
176pub struct PyMappingMethods {
177    pub mp_length: Option<object::lenfunc>,
178    pub mp_subscript: Option<object::binaryfunc>,
179    pub mp_ass_subscript: Option<object::objobjargproc>,
180}
181
182#[cfg(Py_3_10)]
183pub type sendfunc = unsafe extern "C" fn(
184    iter: *mut PyObject,
185    value: *mut PyObject,
186    result: *mut *mut PyObject,
187) -> object::PySendResult;
188
189#[repr(C)]
190#[derive(Clone, Default)]
191pub struct PyAsyncMethods {
192    pub am_await: Option<object::unaryfunc>,
193    pub am_aiter: Option<object::unaryfunc>,
194    pub am_anext: Option<object::unaryfunc>,
195    #[cfg(Py_3_10)]
196    pub am_send: Option<sendfunc>,
197}
198
199#[repr(C)]
200#[derive(Clone, Default)]
201pub struct PyBufferProcs {
202    pub bf_getbuffer: Option<crate::getbufferproc>,
203    pub bf_releasebuffer: Option<crate::releasebufferproc>,
204}
205
206pub type printfunc =
207    unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut ::libc::FILE, arg3: c_int) -> c_int;
208
209#[repr(C)]
210#[derive(Debug)]
211pub struct PyTypeObject {
212    pub ob_base: object::PyVarObject,
213    pub tp_name: *const c_char,
214    pub tp_basicsize: Py_ssize_t,
215    pub tp_itemsize: Py_ssize_t,
216    pub tp_dealloc: Option<object::destructor>,
217    pub tp_vectorcall_offset: Py_ssize_t,
218    pub tp_getattr: Option<object::getattrfunc>,
219    pub tp_setattr: Option<object::setattrfunc>,
220    pub tp_as_async: *mut PyAsyncMethods,
221    pub tp_repr: Option<object::reprfunc>,
222    pub tp_as_number: *mut PyNumberMethods,
223    pub tp_as_sequence: *mut PySequenceMethods,
224    pub tp_as_mapping: *mut PyMappingMethods,
225    pub tp_hash: Option<object::hashfunc>,
226    pub tp_call: Option<object::ternaryfunc>,
227    pub tp_str: Option<object::reprfunc>,
228    pub tp_getattro: Option<object::getattrofunc>,
229    pub tp_setattro: Option<object::setattrofunc>,
230    pub tp_as_buffer: *mut PyBufferProcs,
231    #[cfg(not(Py_GIL_DISABLED))]
232    pub tp_flags: std::ffi::c_ulong,
233    #[cfg(Py_GIL_DISABLED)]
234    pub tp_flags: crate::impl_::AtomicCULong,
235    pub tp_doc: *const c_char,
236    pub tp_traverse: Option<object::traverseproc>,
237    pub tp_clear: Option<object::inquiry>,
238    pub tp_richcompare: Option<object::richcmpfunc>,
239    pub tp_weaklistoffset: Py_ssize_t,
240    pub tp_iter: Option<object::getiterfunc>,
241    pub tp_iternext: Option<object::iternextfunc>,
242    pub tp_methods: *mut PyMethodDef,
243    pub tp_members: *mut PyMemberDef,
244    pub tp_getset: *mut PyGetSetDef,
245    pub tp_base: *mut PyTypeObject,
246    pub tp_dict: *mut object::PyObject,
247    pub tp_descr_get: Option<object::descrgetfunc>,
248    pub tp_descr_set: Option<object::descrsetfunc>,
249    pub tp_dictoffset: Py_ssize_t,
250    pub tp_init: Option<object::initproc>,
251    pub tp_alloc: Option<object::allocfunc>,
252    pub tp_new: Option<object::newfunc>,
253    pub tp_free: Option<object::freefunc>,
254    pub tp_is_gc: Option<object::inquiry>,
255    pub tp_bases: *mut object::PyObject,
256    pub tp_mro: *mut object::PyObject,
257    pub tp_cache: *mut object::PyObject,
258    pub tp_subclasses: *mut object::PyObject,
259    pub tp_weaklist: *mut object::PyObject,
260    pub tp_del: Option<object::destructor>,
261    pub tp_version_tag: c_uint,
262    pub tp_finalize: Option<object::destructor>,
263    pub tp_vectorcall: Option<vectorcallfunc>,
264    #[cfg(Py_3_12)]
265    pub tp_watched: c_char,
266    #[cfg(not(any(PyPy, Py_3_9)))]
267    pub tp_print: Option<printfunc>,
268    #[cfg(py_sys_config = "COUNT_ALLOCS")]
269    pub tp_allocs: Py_ssize_t,
270    #[cfg(py_sys_config = "COUNT_ALLOCS")]
271    pub tp_frees: Py_ssize_t,
272    #[cfg(py_sys_config = "COUNT_ALLOCS")]
273    pub tp_maxalloc: Py_ssize_t,
274    #[cfg(py_sys_config = "COUNT_ALLOCS")]
275    pub tp_prev: *mut PyTypeObject,
276    #[cfg(py_sys_config = "COUNT_ALLOCS")]
277    pub tp_next: *mut PyTypeObject,
278    #[cfg(Py_3_13)]
279    pub tp_versions_used: u16,
280}
281
282#[cfg(Py_3_11)]
283#[repr(C)]
284#[derive(Clone)]
285struct _specialization_cache {
286    getitem: *mut PyObject,
287    #[cfg(Py_3_12)]
288    getitem_version: u32,
289    #[cfg(Py_3_13)]
290    init: *mut PyObject,
291}
292
293#[repr(C)]
294pub struct PyHeapTypeObject {
295    pub ht_type: PyTypeObject,
296    pub as_async: PyAsyncMethods,
297    pub as_number: PyNumberMethods,
298    pub as_mapping: PyMappingMethods,
299    pub as_sequence: PySequenceMethods,
300    pub as_buffer: PyBufferProcs,
301    pub ht_name: *mut object::PyObject,
302    pub ht_slots: *mut object::PyObject,
303    pub ht_qualname: *mut object::PyObject,
304    #[cfg(not(PyPy))]
305    pub ht_cached_keys: *mut c_void,
306    #[cfg(Py_3_9)]
307    pub ht_module: *mut object::PyObject,
308    #[cfg(all(Py_3_11, not(PyPy)))]
309    _ht_tpname: *mut c_char,
310    #[cfg(Py_3_14)]
311    pub ht_token: *mut c_void,
312    #[cfg(all(Py_3_11, not(PyPy)))]
313    _spec_cache: _specialization_cache,
314    #[cfg(all(Py_GIL_DISABLED, Py_3_14))]
315    pub unique_id: Py_ssize_t,
316}
317
318impl Default for PyHeapTypeObject {
319    #[inline]
320    fn default() -> Self {
321        unsafe { mem::zeroed() }
322    }
323}
324
325#[inline]
326#[cfg(not(Py_3_11))]
327pub unsafe fn PyHeapType_GET_MEMBERS(etype: *mut PyHeapTypeObject) -> *mut PyMemberDef {
328    let py_type = object::Py_TYPE(etype as *mut object::PyObject);
329    let ptr = etype.offset((*py_type).tp_basicsize);
330    ptr as *mut PyMemberDef
331}
332
333// skipped private _PyType_Name
334// skipped private _PyType_Lookup
335// skipped private _PyType_LookupRef
336
337extern_libpython! {
338    #[cfg(Py_3_12)]
339    pub fn PyType_GetDict(o: *mut PyTypeObject) -> *mut PyObject;
340
341    #[cfg_attr(PyPy, link_name = "PyPyObject_Print")]
342    pub fn PyObject_Print(o: *mut PyObject, fp: *mut ::libc::FILE, flags: c_int) -> c_int;
343
344    // skipped private _Py_BreakPoint
345    // skipped private _PyObject_Dump
346
347    // skipped _PyObject_GetAttrId
348
349    // skipped private _PyObject_GetDictPtr
350    pub fn PyObject_CallFinalizer(arg1: *mut PyObject);
351    #[cfg_attr(PyPy, link_name = "PyPyObject_CallFinalizerFromDealloc")]
352    pub fn PyObject_CallFinalizerFromDealloc(arg1: *mut PyObject) -> c_int;
353
354    // skipped private _PyObject_GenericGetAttrWithDict
355    // skipped private _PyObject_GenericSetAttrWithDict
356    // skipped private _PyObject_FunctionStr
357}
358
359// skipped Py_SETREF
360// skipped Py_XSETREF
361
362// skipped private _PyObject_ASSERT_FROM
363// skipped private _PyObject_ASSERT_WITH_MSG
364// skipped private _PyObject_ASSERT
365// skipped private _PyObject_ASSERT_FAILED_MSG
366// skipped private _PyObject_AssertFailed
367
368// skipped private _PyTrash_begin
369// skipped private _PyTrash_end
370
371// skipped _PyTrash_thread_deposit_object
372// skipped _PyTrash_thread_destroy_chain
373
374// skipped Py_TRASHCAN_BEGIN
375// skipped Py_TRASHCAN_END
376
377// skipped PyObject_GetItemData
378
379// skipped PyObject_VisitManagedDict
380// skipped _PyObject_SetManagedDict
381// skipped PyObject_ClearManagedDict
382
383// skipped TYPE_MAX_WATCHERS
384
385// skipped PyType_WatchCallback
386// skipped PyType_AddWatcher
387// skipped PyType_ClearWatcher
388// skipped PyType_Watch
389// skipped PyType_Unwatch
390
391// skipped PyUnstable_Type_AssignVersionTag
392
393// skipped PyRefTracerEvent
394
395// skipped PyRefTracer
396// skipped PyRefTracer_SetTracer
397// skipped PyRefTracer_GetTracer
398
399#[cfg(Py_3_14)]
400extern_libpython! {
401    // skipped PyUnstable_Object_EnableDeferredRefcount
402
403    pub fn PyUnstable_Object_IsUniqueReferencedTemporary(obj: *mut PyObject) -> c_int;
404
405    // skipped PyUnstable_IsImmortal
406
407    pub fn PyUnstable_TryIncRef(obj: *mut PyObject) -> c_int;
408
409    pub fn PyUnstable_EnableTryIncRef(obj: *mut PyObject) -> c_void;
410
411    pub fn PyUnstable_Object_IsUniquelyReferenced(op: *mut PyObject) -> c_int;
412}
413
414#[cfg(Py_3_15)]
415extern_libpython! {
416    pub fn PyUnstable_SetImmortal(op: *mut PyObject) -> c_int;
417}