1use crate::{PyObject, Py_ssize_t};
2use std::os::raw::{c_char, c_int};
3
4#[cfg(not(Py_3_11))]
5use crate::Py_buffer;
6
7#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
8use crate::{
9 vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check,
10 PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL,
11};
12#[cfg(Py_3_8)]
13use libc::size_t;
14
15extern "C" {
16 #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
17 pub fn _PyStack_AsDict(values: *const *mut PyObject, kwnames: *mut PyObject) -> *mut PyObject;
18}
19
20#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
21const _PY_FASTCALL_SMALL_STACK: size_t = 5;
22
23extern "C" {
24 #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
25 pub fn _Py_CheckFunctionResult(
26 tstate: *mut PyThreadState,
27 callable: *mut PyObject,
28 result: *mut PyObject,
29 where_: *const c_char,
30 ) -> *mut PyObject;
31
32 #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
33 pub fn _PyObject_MakeTpCall(
34 tstate: *mut PyThreadState,
35 callable: *mut PyObject,
36 args: *const *mut PyObject,
37 nargs: Py_ssize_t,
38 keywords: *mut PyObject,
39 ) -> *mut PyObject;
40}
41
42#[cfg(Py_3_8)]
43pub const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =
44 1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);
45
46#[cfg(Py_3_8)]
47#[inline(always)]
48pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t {
49 let n = n & !PY_VECTORCALL_ARGUMENTS_OFFSET;
50 n.try_into().expect("cannot fail due to mask")
51}
52
53#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
54#[inline(always)]
55pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option<vectorcallfunc> {
56 assert!(!callable.is_null());
57 let tp = crate::Py_TYPE(callable);
58 if PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL) == 0 {
59 return None;
60 }
61 assert!(PyCallable_Check(callable) > 0);
62 let offset = (*tp).tp_vectorcall_offset;
63 assert!(offset > 0);
64 let ptr = callable.cast::<c_char>().offset(offset).cast();
65 *ptr
66}
67
68#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
69#[inline(always)]
70pub unsafe fn _PyObject_VectorcallTstate(
71 tstate: *mut PyThreadState,
72 callable: *mut PyObject,
73 args: *const *mut PyObject,
74 nargsf: size_t,
75 kwnames: *mut PyObject,
76) -> *mut PyObject {
77 assert!(kwnames.is_null() || PyTuple_Check(kwnames) > 0);
78 assert!(!args.is_null() || PyVectorcall_NARGS(nargsf) == 0);
79
80 match PyVectorcall_Function(callable) {
81 None => {
82 let nargs = PyVectorcall_NARGS(nargsf);
83 _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames)
84 }
85 Some(func) => {
86 let res = func(callable, args, nargsf, kwnames);
87 _Py_CheckFunctionResult(tstate, callable, res, std::ptr::null_mut())
88 }
89 }
90}
91
92#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
93#[inline(always)]
94pub unsafe fn PyObject_Vectorcall(
95 callable: *mut PyObject,
96 args: *const *mut PyObject,
97 nargsf: size_t,
98 kwnames: *mut PyObject,
99) -> *mut PyObject {
100 _PyObject_VectorcallTstate(PyThreadState_GET(), callable, args, nargsf, kwnames)
101}
102
103extern "C" {
104 #[cfg(all(PyPy, Py_3_8))]
105 #[cfg_attr(not(Py_3_9), link_name = "_PyPyObject_Vectorcall")]
106 #[cfg_attr(Py_3_9, link_name = "PyPyObject_Vectorcall")]
107 pub fn PyObject_Vectorcall(
108 callable: *mut PyObject,
109 args: *const *mut PyObject,
110 nargsf: size_t,
111 kwnames: *mut PyObject,
112 ) -> *mut PyObject;
113
114 #[cfg(Py_3_8)]
115 #[cfg_attr(
116 all(not(any(PyPy, GraalPy)), not(Py_3_9)),
117 link_name = "_PyObject_VectorcallDict"
118 )]
119 #[cfg_attr(all(PyPy, not(Py_3_9)), link_name = "_PyPyObject_VectorcallDict")]
120 #[cfg_attr(all(PyPy, Py_3_9), link_name = "PyPyObject_VectorcallDict")]
121 pub fn PyObject_VectorcallDict(
122 callable: *mut PyObject,
123 args: *const *mut PyObject,
124 nargsf: size_t,
125 kwdict: *mut PyObject,
126 ) -> *mut PyObject;
127
128 #[cfg(Py_3_8)]
129 #[cfg_attr(not(any(Py_3_9, PyPy)), link_name = "_PyVectorcall_Call")]
130 #[cfg_attr(PyPy, link_name = "PyPyVectorcall_Call")]
131 pub fn PyVectorcall_Call(
132 callable: *mut PyObject,
133 tuple: *mut PyObject,
134 dict: *mut PyObject,
135 ) -> *mut PyObject;
136}
137
138#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
139#[inline(always)]
140pub unsafe fn _PyObject_FastCallTstate(
141 tstate: *mut PyThreadState,
142 func: *mut PyObject,
143 args: *const *mut PyObject,
144 nargs: Py_ssize_t,
145) -> *mut PyObject {
146 _PyObject_VectorcallTstate(tstate, func, args, nargs as size_t, std::ptr::null_mut())
147}
148
149#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
150#[inline(always)]
151pub unsafe fn _PyObject_FastCall(
152 func: *mut PyObject,
153 args: *const *mut PyObject,
154 nargs: Py_ssize_t,
155) -> *mut PyObject {
156 _PyObject_FastCallTstate(PyThreadState_GET(), func, args, nargs)
157}
158
159#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
160#[inline(always)]
161pub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject {
162 _PyObject_VectorcallTstate(
163 PyThreadState_GET(),
164 func,
165 std::ptr::null_mut(),
166 0,
167 std::ptr::null_mut(),
168 )
169}
170
171extern "C" {
172 #[cfg(PyPy)]
173 #[link_name = "_PyPyObject_CallNoArg"]
174 pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject;
175}
176
177#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]
178#[inline(always)]
179pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {
180 assert!(!arg.is_null());
181 let args_array = [std::ptr::null_mut(), arg];
182 let args = args_array.as_ptr().offset(1); let tstate = PyThreadState_GET();
184 let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
185 _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut())
186}
187
188extern "C" {
189 #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
190 pub fn PyObject_VectorcallMethod(
191 name: *mut PyObject,
192 args: *const *mut PyObject,
193 nargsf: size_t,
194 kwnames: *mut PyObject,
195 ) -> *mut PyObject;
196}
197
198#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
199#[inline(always)]
200pub unsafe fn PyObject_CallMethodNoArgs(
201 self_: *mut PyObject,
202 name: *mut PyObject,
203) -> *mut PyObject {
204 PyObject_VectorcallMethod(
205 name,
206 &self_,
207 1 | PY_VECTORCALL_ARGUMENTS_OFFSET,
208 std::ptr::null_mut(),
209 )
210}
211
212#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
213#[inline(always)]
214pub unsafe fn PyObject_CallMethodOneArg(
215 self_: *mut PyObject,
216 name: *mut PyObject,
217 arg: *mut PyObject,
218) -> *mut PyObject {
219 let args = [self_, arg];
220 assert!(!arg.is_null());
221 PyObject_VectorcallMethod(
222 name,
223 args.as_ptr(),
224 2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
225 std::ptr::null_mut(),
226 )
227}
228
229extern "C" {
236 #[cfg_attr(PyPy, link_name = "PyPyObject_LengthHint")]
237 pub fn PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) -> Py_ssize_t;
238
239 #[cfg(not(Py_3_11))] #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))]
241 pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int;
242}
243
244#[cfg(not(any(Py_3_9, PyPy)))]
245#[inline]
246pub unsafe fn PyObject_CheckBuffer(o: *mut PyObject) -> c_int {
247 let tp_as_buffer = (*crate::Py_TYPE(o)).tp_as_buffer;
248 (!tp_as_buffer.is_null() && (*tp_as_buffer).bf_getbuffer.is_some()) as c_int
249}
250
251#[cfg(not(Py_3_11))] extern "C" {
253 #[cfg_attr(PyPy, link_name = "PyPyObject_GetBuffer")]
254 pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int;
255 #[cfg_attr(PyPy, link_name = "PyPyBuffer_GetPointer")]
256 pub fn PyBuffer_GetPointer(
257 view: *mut Py_buffer,
258 indices: *mut Py_ssize_t,
259 ) -> *mut std::os::raw::c_void;
260 #[cfg_attr(PyPy, link_name = "PyPyBuffer_SizeFromFormat")]
261 pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t;
262 #[cfg_attr(PyPy, link_name = "PyPyBuffer_ToContiguous")]
263 pub fn PyBuffer_ToContiguous(
264 buf: *mut std::os::raw::c_void,
265 view: *mut Py_buffer,
266 len: Py_ssize_t,
267 order: c_char,
268 ) -> c_int;
269 #[cfg_attr(PyPy, link_name = "PyPyBuffer_FromContiguous")]
270 pub fn PyBuffer_FromContiguous(
271 view: *mut Py_buffer,
272 buf: *mut std::os::raw::c_void,
273 len: Py_ssize_t,
274 order: c_char,
275 ) -> c_int;
276 pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int;
277 #[cfg_attr(PyPy, link_name = "PyPyBuffer_IsContiguous")]
278 pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int;
279 pub fn PyBuffer_FillContiguousStrides(
280 ndims: c_int,
281 shape: *mut Py_ssize_t,
282 strides: *mut Py_ssize_t,
283 itemsize: c_int,
284 fort: c_char,
285 );
286 #[cfg_attr(PyPy, link_name = "PyPyBuffer_FillInfo")]
287 pub fn PyBuffer_FillInfo(
288 view: *mut Py_buffer,
289 o: *mut PyObject,
290 buf: *mut std::os::raw::c_void,
291 len: Py_ssize_t,
292 readonly: c_int,
293 flags: c_int,
294 ) -> c_int;
295 #[cfg_attr(PyPy, link_name = "PyPyBuffer_Release")]
296 pub fn PyBuffer_Release(view: *mut Py_buffer);
297}
298
299pub const PY_ITERSEARCH_COUNT: c_int = 1;
308pub const PY_ITERSEARCH_INDEX: c_int = 2;
309pub const PY_ITERSEARCH_CONTAINS: c_int = 3;
310
311extern "C" {
312 #[cfg(not(any(PyPy, GraalPy)))]
313 pub fn _PySequence_IterSearch(
314 seq: *mut PyObject,
315 obj: *mut PyObject,
316 operation: c_int,
317 ) -> Py_ssize_t;
318}
319
320