Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/5711.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add FFI definitions `PyThreadState_GetInterpreter` and `PyThreadState_GetID` on Python 3.9+, `PyThreadState_EnterTracing` and `PyThreadState_LeaveTracing` on Python 3.11+, `PyThreadState_GetUnchecked` on Python 3.13+, and `compat::PyThreadState_GetUnchecked`.
1 change: 1 addition & 0 deletions newsfragments/5711.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Correct FFI definition for `PyThreadState_GetFrame` to mark it available with abi3 in 3.10+.
1 change: 1 addition & 0 deletions newsfragments/5711.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove private FFI definitions `_PyFrameEvalFunction`, `_PyInterpreterState_GetEvalFrameFunc` and `_PyInterpreterState_SetEvalFrameFunc`.
2 changes: 1 addition & 1 deletion pyo3-ffi/src/ceval.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::object::PyObject;
use crate::pystate::PyThreadState;
use crate::pytypedefs::PyThreadState;
use std::ffi::{c_char, c_int, c_void};

extern "C" {
Expand Down
4 changes: 0 additions & 4 deletions pyo3-ffi/src/code.rs

This file was deleted.

11 changes: 11 additions & 0 deletions pyo3-ffi/src/compat/py_3_13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,14 @@ compat_function!(
result
}
);

#[cfg(not(Py_LIMITED_API))]
compat_function!(
originally_defined_for(Py_3_13);

#[inline]
pub unsafe fn PyThreadState_GetUnchecked(
) -> *mut crate::PyThreadState {
crate::_PyThreadState_UncheckedGet()
}
);
9 changes: 2 additions & 7 deletions pyo3-ffi/src/cpython/code.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::object::*;
use crate::pyport::Py_ssize_t;

#[cfg(not(GraalPy))]
use crate::PyCodeObject;
#[cfg(not(GraalPy))]
use std::ffi::c_char;
use std::ffi::{c_int, c_void};
Expand Down Expand Up @@ -32,13 +34,6 @@ use std::ptr::addr_of_mut;

// skipped private _PyExecutorArray

opaque_struct!(
#[doc = "A Python code object.\n"]
#[doc = "\n"]
#[doc = "`pyo3-ffi` does not expose the contents of this struct, as it has no stability guarantees."]
pub PyCodeObject
);

/* Masks for co_flags */
pub const CO_OPTIMIZED: c_int = 0x0001;
pub const CO_NEWLOCALS: c_int = 0x0002;
Expand Down
6 changes: 3 additions & 3 deletions pyo3-ffi/src/cpython/frameobject.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#[cfg(not(GraalPy))]
use crate::cpython::code::PyCodeObject;
#[cfg(not(GraalPy))]
use crate::object::*;
#[cfg(not(GraalPy))]
use crate::pystate::PyThreadState;
use crate::PyCodeObject;
use crate::PyFrameObject;
#[cfg(not(GraalPy))]
use crate::PyThreadState;
#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]
use std::ffi::c_char;
use std::ffi::c_int;
Expand Down
86 changes: 29 additions & 57 deletions pyo3-ffi/src/cpython/pystate.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
#[cfg(not(PyPy))]
use crate::PyThreadState;
use crate::{PyFrameObject, PyInterpreterState, PyObject};
use std::ffi::c_int;

// skipped _PyInterpreterState_RequiresIDRef
// skipped _PyInterpreterState_RequireIDRef

// skipped _PyInterpreterState_GetMainModule
// skipped private _PyInterpreterState_RequiresIDRef
// skipped private _PyInterpreterState_RequireIDRef

pub type Py_tracefunc = unsafe extern "C" fn(
obj: *mut PyObject,
Expand All @@ -24,11 +21,14 @@ pub const PyTrace_C_EXCEPTION: c_int = 5;
pub const PyTrace_C_RETURN: c_int = 6;
pub const PyTrace_OPCODE: c_int = 7;

// skipped PyTraceInfo
// skipped CFrame
// skipped private _Py_MAX_SCRIPT_PATH_SIZE
// skipped private _PyRemoteDebuggerSupport

/// Private structure used inline in `PyGenObject`
#[cfg(not(PyPy))]
///
/// `PyGenObject` was made opaque in Python 3.14, so we don't bother defining this
/// structure for that version and later.
#[cfg(not(any(PyPy, Py_3_14)))]
#[repr(C)]
#[derive(Clone, Copy)]
pub(crate) struct _PyErr_StackItem {
Expand All @@ -40,20 +40,30 @@ pub(crate) struct _PyErr_StackItem {
previous_item: *mut _PyErr_StackItem,
}

// skipped _PyStackChunk
// skipped _ts (aka PyThreadState)
// skipped private _PyStackChunk

// skipped private _PY_DATA_STACK_CHUNK_SIZE
// skipped private _ts (aka PyThreadState)

extern "C" {
// skipped _PyThreadState_Prealloc
// skipped _PyThreadState_UncheckedGet
// skipped _PyThreadState_GetDict
#[cfg(Py_3_13)]
pub fn PyThreadState_GetUnchecked() -> *mut PyThreadState;

#[cfg(not(Py_3_13))]
pub(crate) fn _PyThreadState_UncheckedGet() -> *mut PyThreadState;

#[cfg(Py_3_11)]
pub fn PyThreadState_EnterTracing(state: *mut PyThreadState);
#[cfg(Py_3_11)]
pub fn PyThreadState_LeaveTracing(state: *mut PyThreadState);

#[cfg_attr(PyPy, link_name = "PyPyGILState_Check")]
pub fn PyGILState_Check() -> c_int;

// skipped _PyGILState_GetInterpreterStateUnsafe
// skipped _PyThread_CurrentFrames
// skipped _PyThread_CurrentExceptions
// skipped private _PyThread_CurrentFrames

// skipped PyUnstable_ThreadState_SetStackProtection
// skipped PyUnstable_ThreadState_ResetStackProtection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here - seems reasonable to expose these to me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this one I am going to skip for now, just because "unstable" APIs seem to imply they're more likely to have churn so I'm tempted to wait to take on the maintenance burden until someone asks to use these.


#[cfg(not(PyPy))]
pub fn PyInterpreterState_Main() -> *mut PyInterpreterState;
Expand All @@ -70,44 +80,6 @@ extern "C" {
pub fn PyThreadState_DeleteCurrent();
}

#[cfg(all(Py_3_9, not(any(Py_3_11, PyPy))))]
pub type _PyFrameEvalFunction = extern "C" fn(
*mut crate::PyThreadState,
*mut crate::PyFrameObject,
c_int,
) -> *mut crate::object::PyObject;

#[cfg(all(Py_3_11, not(PyPy)))]
pub type _PyFrameEvalFunction = extern "C" fn(
*mut crate::PyThreadState,
*mut crate::_PyInterpreterFrame,
c_int,
) -> *mut crate::object::PyObject;

#[cfg(all(Py_3_9, not(PyPy)))]
extern "C" {
/// Get the frame evaluation function.
pub fn _PyInterpreterState_GetEvalFrameFunc(
interp: *mut PyInterpreterState,
) -> _PyFrameEvalFunction;

///Set the frame evaluation function.
pub fn _PyInterpreterState_SetEvalFrameFunc(
interp: *mut PyInterpreterState,
eval_frame: _PyFrameEvalFunction,
);
}

// skipped _PyInterpreterState_GetConfig
// skipped _PyInterpreterState_GetConfigCopy
// skipped _PyInterpreterState_SetConfig
// skipped _Py_GetConfig

// skipped _PyCrossInterpreterData
// skipped _PyObject_GetCrossInterpreterData
// skipped _PyCrossInterpreterData_NewObject
// skipped _PyCrossInterpreterData_Release
// skipped _PyObject_CheckCrossInterpreterData
// skipped crossinterpdatafunc
// skipped _PyCrossInterpreterData_RegisterClass
// skipped _PyCrossInterpreterData_Lookup
// skipped private _PyFrameEvalFunction
// skipped private _PyInterpreterState_GetEvalFrameFunc
// skipped private _PyInterpreterState_SetEvalFrameFunc
4 changes: 0 additions & 4 deletions pyo3-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,6 @@ pub use self::boolobject::*;
pub use self::bytearrayobject::*;
pub use self::bytesobject::*;
pub use self::ceval::*;
#[cfg(Py_LIMITED_API)]
pub use self::code::*;
pub use self::codecs::*;
pub use self::compile::*;
pub use self::complexobject::*;
Expand Down Expand Up @@ -455,8 +453,6 @@ mod bytesobject;
// skipped cellobject.h
mod ceval;
// skipped classobject.h
#[cfg(Py_LIMITED_API)]
mod code;
mod codecs;
mod compile;
mod complexobject;
Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/src/pylifecycle.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pystate::PyThreadState;
use crate::pytypedefs::PyThreadState;

use libc::wchar_t;
use std::ffi::{c_char, c_int};
Expand Down
23 changes: 11 additions & 12 deletions pyo3-ffi/src/pystate.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use crate::moduleobject::PyModuleDef;
use crate::object::PyObject;
use crate::pytypedefs::{PyInterpreterState, PyThreadState};
use std::ffi::c_int;

#[cfg(all(Py_3_10, not(PyPy), not(Py_LIMITED_API)))]
#[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]
#[cfg(not(PyPy))]
use crate::PyFrameObject;

#[cfg(not(PyPy))]
use std::ffi::c_long;

pub const MAX_CO_EXTRA_USERS: c_int = 255;

opaque_struct!(pub PyThreadState);
opaque_struct!(pub PyInterpreterState);

extern "C" {
#[cfg(not(PyPy))]
pub fn PyInterpreterState_New() -> *mut PyInterpreterState;
Expand All @@ -32,7 +31,6 @@ extern "C" {

#[cfg_attr(PyPy, link_name = "PyPyState_AddModule")]
pub fn PyState_AddModule(arg1: *mut PyObject, arg2: *mut PyModuleDef) -> c_int;

#[cfg_attr(PyPy, link_name = "PyPyState_RemoveModule")]
pub fn PyState_RemoveModule(arg1: *mut PyModuleDef) -> c_int;

Expand Down Expand Up @@ -62,15 +60,16 @@ extern "C" {
pub fn PyThreadState_GetDict() -> *mut PyObject;
#[cfg(not(PyPy))]
pub fn PyThreadState_SetAsyncExc(arg1: c_long, arg2: *mut PyObject) -> c_int;
}

// skipped non-limited / 3.9 PyThreadState_GetInterpreter
// skipped non-limited / 3.9 PyThreadState_GetID

extern "C" {
// PyThreadState_GetFrame
#[cfg(all(Py_3_10, not(PyPy), not(Py_LIMITED_API)))]
#[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]
#[cfg(not(PyPy))]
pub fn PyThreadState_GetInterpreter(arg1: *mut PyThreadState) -> *mut PyInterpreterState;
#[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]
#[cfg(not(PyPy))]
pub fn PyThreadState_GetFrame(arg1: *mut PyThreadState) -> *mut PyFrameObject;
#[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]
#[cfg(not(PyPy))]
pub fn PyThreadState_GetID(arg1: *mut PyThreadState) -> i64;
}

#[repr(C)]
Expand Down
17 changes: 15 additions & 2 deletions pyo3-ffi/src/pytypedefs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
// TODO: Created this file as part of fixing pyframe.rs and cpython/pyframe.rs
// TODO: Finish defining or moving declarations now in Include/pytypedefs.h
// NB: unlike C, we do not need to forward declare structs in Rust.
// So we only define opaque structs for those which do not have public structure.

// PyModuleDef
// PyModuleDef_Slot
// PyMethodDef
// PyGetSetDef
// PyMemberDef

// PyObject
// PyLongObject
// PyTypeObject
opaque_struct!(pub PyCodeObject);
opaque_struct!(pub PyFrameObject);

opaque_struct!(pub PyThreadState);
opaque_struct!(pub PyInterpreterState);
Loading