Skip to main content

pyo3_ffi/
ceval.rs

1use crate::object::PyObject;
2use crate::pytypedefs::PyThreadState;
3use core::ffi::{c_char, c_int, c_void};
4
5extern_libpython! {
6    #[cfg_attr(PyPy, link_name = "PyPyEval_EvalCode")]
7    pub fn PyEval_EvalCode(
8        arg1: *mut PyObject,
9        arg2: *mut PyObject,
10        arg3: *mut PyObject,
11    ) -> *mut PyObject;
12
13    pub fn PyEval_EvalCodeEx(
14        co: *mut PyObject,
15        globals: *mut PyObject,
16        locals: *mut PyObject,
17        args: *const *mut PyObject,
18        argc: c_int,
19        kwds: *const *mut PyObject,
20        kwdc: c_int,
21        defs: *const *mut PyObject,
22        defc: c_int,
23        kwdefs: *mut PyObject,
24        closure: *mut PyObject,
25    ) -> *mut PyObject;
26
27    #[cfg(not(Py_3_13))]
28    #[deprecated(note = "Python 3.9")]
29    #[cfg_attr(PyPy, link_name = "PyPyEval_CallObjectWithKeywords")]
30    pub fn PyEval_CallObjectWithKeywords(
31        func: *mut PyObject,
32        obj: *mut PyObject,
33        kwargs: *mut PyObject,
34    ) -> *mut PyObject;
35}
36
37#[cfg(not(Py_3_13))]
38#[deprecated(note = "Python 3.9")]
39#[inline]
40pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {
41    #[allow(deprecated)]
42    PyEval_CallObjectWithKeywords(func, arg, core::ptr::null_mut())
43}
44
45extern_libpython! {
46    #[cfg(not(Py_3_13))]
47    #[deprecated(note = "Python 3.9")]
48    #[cfg_attr(PyPy, link_name = "PyPyEval_CallFunction")]
49    pub fn PyEval_CallFunction(obj: *mut PyObject, format: *const c_char, ...) -> *mut PyObject;
50    #[cfg(not(Py_3_13))]
51    #[deprecated(note = "Python 3.9")]
52    #[cfg_attr(PyPy, link_name = "PyPyEval_CallMethod")]
53    pub fn PyEval_CallMethod(
54        obj: *mut PyObject,
55        methodname: *const c_char,
56        format: *const c_char,
57        ...
58    ) -> *mut PyObject;
59    #[cfg_attr(PyPy, link_name = "PyPyEval_GetBuiltins")]
60    pub fn PyEval_GetBuiltins() -> *mut PyObject;
61    #[cfg_attr(PyPy, link_name = "PyPyEval_GetGlobals")]
62    pub fn PyEval_GetGlobals() -> *mut PyObject;
63    #[cfg_attr(PyPy, link_name = "PyPyEval_GetLocals")]
64    pub fn PyEval_GetLocals() -> *mut PyObject;
65    #[cfg_attr(PyPy, link_name = "PyPyEval_GetFrame")]
66    pub fn PyEval_GetFrame() -> *mut crate::PyFrameObject;
67
68    #[cfg(Py_3_13)]
69    #[cfg_attr(PyPy, link_name = "PyPyEval_GetFrameBuiltins")]
70    pub fn PyEval_GetFrameBuiltins() -> *mut PyObject;
71    #[cfg(Py_3_13)]
72    #[cfg_attr(PyPy, link_name = "PyPyEval_GetFrameGlobals")]
73    pub fn PyEval_GetFrameGlobals() -> *mut PyObject;
74    #[cfg(Py_3_13)]
75    #[cfg_attr(PyPy, link_name = "PyPyEval_GetFrameLocals")]
76    pub fn PyEval_GetFrameLocals() -> *mut PyObject;
77
78    #[cfg_attr(PyPy, link_name = "PyPy_AddPendingCall")]
79    pub fn Py_AddPendingCall(
80        func: Option<extern "C" fn(arg1: *mut c_void) -> c_int>,
81        arg: *mut c_void,
82    ) -> c_int;
83    #[cfg_attr(PyPy, link_name = "PyPy_MakePendingCalls")]
84    pub fn Py_MakePendingCalls() -> c_int;
85
86    #[cfg_attr(PyPy, link_name = "PyPy_SetRecursionLimit")]
87    pub fn Py_SetRecursionLimit(arg1: c_int);
88    #[cfg_attr(PyPy, link_name = "PyPy_GetRecursionLimit")]
89    pub fn Py_GetRecursionLimit() -> c_int;
90
91    #[cfg_attr(PyPy, link_name = "PyPy_EnterRecursiveCall")]
92    pub fn Py_EnterRecursiveCall(arg1: *const c_char) -> c_int;
93    #[cfg_attr(PyPy, link_name = "PyPy_LeaveRecursiveCall")]
94    pub fn Py_LeaveRecursiveCall();
95
96    #[cfg_attr(PyPy, link_name = "PyPyEval_GetFuncName")]
97    pub fn PyEval_GetFuncName(arg1: *mut PyObject) -> *const c_char;
98    #[cfg_attr(PyPy, link_name = "PyPyEval_GetFuncDesc")]
99    pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char;
100
101    #[cfg_attr(PyPy, link_name = "PyPyEval_EvalFrame")]
102    pub fn PyEval_EvalFrame(arg1: *mut crate::PyFrameObject) -> *mut PyObject;
103    #[cfg_attr(PyPy, link_name = "PyPyEval_EvalFrameEx")]
104    pub fn PyEval_EvalFrameEx(f: *mut crate::PyFrameObject, exc: c_int) -> *mut PyObject;
105
106    #[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")]
107    pub fn PyEval_SaveThread() -> *mut PyThreadState;
108
109    #[cfg(not(Py_3_13))]
110    #[cfg_attr(PyPy, link_name = "PyPyEval_ThreadsInitialized")]
111    #[deprecated(
112        note = "Deprecated in Python 3.9, this function always returns true in Python 3.7 or newer."
113    )]
114    pub fn PyEval_ThreadsInitialized() -> c_int;
115    #[cfg_attr(PyPy, link_name = "PyPyEval_InitThreads")]
116    #[deprecated(
117        note = "Deprecated in Python 3.9, this function does nothing in Python 3.7 or newer."
118    )]
119    pub fn PyEval_InitThreads();
120    #[cfg(not(Py_3_13))]
121    #[deprecated(note = "Deprecated in Python 3.2")]
122    pub fn PyEval_AcquireLock();
123    #[cfg(not(Py_3_13))]
124    #[deprecated(note = "Deprecated in Python 3.2")]
125    pub fn PyEval_ReleaseLock();
126    #[cfg_attr(PyPy, link_name = "PyPyEval_AcquireThread")]
127    pub fn PyEval_AcquireThread(tstate: *mut PyThreadState);
128    #[cfg_attr(PyPy, link_name = "PyPyEval_ReleaseThread")]
129    pub fn PyEval_ReleaseThread(tstate: *mut PyThreadState);
130}
131
132// PyEval_RestoreThread calls take_gil, which calls pthread_exit on non-main threads
133// during interpreter finalization on Python < 3.14. Redirect to the "safe" version that hangs instead,
134// as Python 3.14 does.
135// See https://github.com/rust-lang/rust/issues/135929
136// C-unwind only supported (and necessary) since 1.71. Python 3.14+ does not do
137// pthread_exit from PyEval_RestoreThread (https://github.com/python/cpython/issues/87135).
138#[cfg(not(any(Py_3_14, target_arch = "wasm32")))]
139mod raw {
140    use crate::pytypedefs::PyThreadState;
141    extern_libpython! { "C-unwind" {
142        #[cfg_attr(PyPy, link_name = "PyPyEval_RestoreThread")]
143        pub fn PyEval_RestoreThread(tstate: *mut PyThreadState);
144    }}
145}
146
147#[cfg(any(Py_3_14, target_arch = "wasm32"))]
148extern_libpython! {
149    #[cfg_attr(PyPy, link_name = "PyPyEval_RestoreThread")]
150    pub fn PyEval_RestoreThread(tstate: *mut PyThreadState);
151}
152
153#[cfg(not(any(Py_3_14, target_arch = "wasm32")))]
154pub unsafe extern "C" fn PyEval_RestoreThread(tstate: *mut PyThreadState) {
155    // Same note as in PyGILState_Ensure
156    let guard = crate::impl_::HangThread;
157    raw::PyEval_RestoreThread(tstate);
158    core::mem::forget(guard);
159}
160
161// skipped Py_BEGIN_ALLOW_THREADS
162// skipped Py_BLOCK_THREADS
163// skipped Py_UNBLOCK_THREADS
164// skipped Py_END_ALLOW_THREADS
165// skipped FVC_MASK
166// skipped FVC_NONE
167// skipped FVC_STR
168// skipped FVC_REPR
169// skipped FVC_ASCII
170// skipped FVS_MASK
171// skipped FVS_HAVE_SPEC
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here