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
3 changes: 3 additions & 0 deletions newsfragments/5154.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* added missing ffi functions for `PyFrameObject` but without
including unstable API from python 3.13
* moved ffi functions to correct files to mach CPython as of 3.13
1 change: 1 addition & 0 deletions newsfragments/5154.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Removed access to internals of PyFrameObject
50 changes: 2 additions & 48 deletions pyo3-ffi/src/cpython/frameobject.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#[cfg(not(GraalPy))]
use crate::cpython::code::PyCodeObject;
#[cfg(not(GraalPy))]
use crate::object::*;
#[cfg(not(GraalPy))]
use crate::pystate::PyThreadState;
use crate::PyFrameObject;
#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]
use std::os::raw::c_char;
use std::os::raw::c_int;
use std::ptr::addr_of_mut;

#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]
pub type PyFrameState = c_char;
Expand All @@ -20,55 +21,10 @@ pub struct PyTryBlock {
pub b_level: c_int,
}

#[repr(C)]
#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]
pub struct PyFrameObject {
Comment on lines -23 to -25
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should add a 5154.removed.md to note that we no longer offer access to the frame object internal structure on versions before 3.11.

pub ob_base: PyVarObject,
pub f_back: *mut PyFrameObject,
pub f_code: *mut PyCodeObject,
pub f_builtins: *mut PyObject,
pub f_globals: *mut PyObject,
pub f_locals: *mut PyObject,
pub f_valuestack: *mut *mut PyObject,

#[cfg(not(Py_3_10))]
pub f_stacktop: *mut *mut PyObject,
pub f_trace: *mut PyObject,
#[cfg(Py_3_10)]
pub f_stackdepth: c_int,
pub f_trace_lines: c_char,
pub f_trace_opcodes: c_char,

pub f_gen: *mut PyObject,

pub f_lasti: c_int,
pub f_lineno: c_int,
pub f_iblock: c_int,
#[cfg(not(Py_3_10))]
pub f_executing: c_char,
#[cfg(Py_3_10)]
pub f_state: PyFrameState,
pub f_blockstack: [PyTryBlock; crate::CO_MAXBLOCKS],
pub f_localsplus: [*mut PyObject; 1],
}

#[cfg(any(PyPy, GraalPy, Py_3_11))]
opaque_struct!(pub PyFrameObject);

// skipped _PyFrame_IsRunnable
// skipped _PyFrame_IsExecuting
// skipped _PyFrameHasCompleted

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
pub static mut PyFrame_Type: PyTypeObject;
}

#[inline]
pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut!(PyFrame_Type)) as c_int
}

extern "C" {
#[cfg(not(GraalPy))]
#[cfg_attr(PyPy, link_name = "PyPyFrame_New")]
Expand All @@ -89,8 +45,6 @@ extern "C" {
pub fn PyFrame_FastToLocals(f: *mut PyFrameObject);

// skipped _PyFrame_DebugMallocStats
#[cfg(all(Py_3_9, not(PyPy)))]
pub fn PyFrame_GetBack(f: *mut PyFrameObject) -> *mut PyFrameObject;

#[cfg(not(Py_3_9))]
pub fn PyFrame_ClearFreeList() -> c_int;
Expand Down
1 change: 0 additions & 1 deletion pyo3-ffi/src/cpython/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ pub use self::object::*;
pub use self::objimpl::*;
pub use self::pydebug::*;
pub use self::pyerrors::*;
#[cfg(all(Py_3_11, not(PyPy)))]
pub use self::pyframe::*;
#[cfg(any(not(PyPy), Py_3_13))]
pub use self::pyhash::*;
Expand Down
59 changes: 59 additions & 0 deletions pyo3-ffi/src/cpython/pyframe.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
#[cfg(any(Py_3_11, all(Py_3_9, not(PyPy))))]
use crate::PyFrameObject;
use crate::{PyObject, PyTypeObject, Py_TYPE};
#[cfg(Py_3_12)]
use std::os::raw::c_char;
use std::os::raw::c_int;
use std::ptr::addr_of_mut;

// NB used in `_PyEval_EvalFrameDefault`, maybe we remove this too.
#[cfg(all(Py_3_11, not(PyPy)))]
opaque_struct!(pub _PyInterpreterFrame);

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
pub static mut PyFrame_Type: PyTypeObject;

#[cfg(Py_3_13)]
pub static mut PyFrameLocalsProxy_Type: PyTypeObject;
}

#[inline]
pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut!(PyFrame_Type)) as c_int
}

#[cfg(Py_3_13)]
#[inline]
pub unsafe fn PyFrameLocalsProxy_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut!(PyFrameLocalsProxy_Type)) as c_int
}

extern "C" {
#[cfg(all(Py_3_9, not(PyPy)))]
pub fn PyFrame_GetBack(frame: *mut PyFrameObject) -> *mut PyFrameObject;

#[cfg(Py_3_11)]
pub fn PyFrame_GetLocals(frame: *mut PyFrameObject) -> *mut PyObject;

#[cfg(Py_3_11)]
pub fn PyFrame_GetGlobals(frame: *mut PyFrameObject) -> *mut PyObject;

#[cfg(Py_3_11)]
pub fn PyFrame_GetBuiltins(frame: *mut PyFrameObject) -> *mut PyObject;

#[cfg(Py_3_11)]
pub fn PyFrame_GetGenerator(frame: *mut PyFrameObject) -> *mut PyObject;

#[cfg(Py_3_11)]
pub fn PyFrame_GetLasti(frame: *mut PyFrameObject) -> c_int;

#[cfg(Py_3_12)]
pub fn PyFrame_GetVar(frame: *mut PyFrameObject, name: *mut PyObject) -> *mut PyObject;

#[cfg(Py_3_12)]
pub fn PyFrame_GetVarString(frame: *mut PyFrameObject, name: *mut c_char) -> *mut PyObject;

// skipped PyUnstable_InterpreterFrame_GetCode
// skipped PyUnstable_InterpreterFrame_GetLasti
// skipped PyUnstable_InterpreterFrame_GetLine
// skipped PyUnstable_ExecutableKinds

}
2 changes: 2 additions & 0 deletions pyo3-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ pub use self::pyport::*;
pub use self::pystate::*;
pub use self::pystrtod::*;
pub use self::pythonrun::*;
pub use self::pytypedefs::*;
pub use self::rangeobject::*;
pub use self::refcount::*;
pub use self::setobject::*;
Expand Down Expand Up @@ -540,6 +541,7 @@ mod pythonrun;
mod pystrtod;
// skipped pythread.h
// skipped pytime.h
mod pytypedefs;
mod rangeobject;
mod refcount;
mod setobject;
Expand Down
11 changes: 5 additions & 6 deletions pyo3-ffi/src/pyframe.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#[allow(unused_imports)]
use crate::object::PyObject;
#[cfg(not(GraalPy))]
#[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
use crate::PyCodeObject;
#[cfg(not(Py_LIMITED_API))]
use crate::PyFrameObject;
use std::os::raw::c_int;

#[cfg(Py_LIMITED_API)]
opaque_struct!(pub PyFrameObject);

extern "C" {
pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int;
pub fn PyFrame_GetLineNumber(frame: *mut PyFrameObject) -> c_int;

#[cfg(not(GraalPy))]
#[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]
pub fn PyFrame_GetCode(f: *mut PyFrameObject) -> *mut PyCodeObject;
pub fn PyFrame_GetCode(frame: *mut PyFrameObject) -> *mut PyCodeObject;
}
5 changes: 3 additions & 2 deletions pyo3-ffi/src/pystate.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#[cfg(all(Py_3_10, not(PyPy), not(Py_LIMITED_API)))]
use crate::frameobject::PyFrameObject;
use crate::moduleobject::PyModuleDef;
use crate::object::PyObject;
use std::os::raw::c_int;

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

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

Expand Down
4 changes: 4 additions & 0 deletions pyo3-ffi/src/pytypedefs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// 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
Comment on lines +1 to +2
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

👍


opaque_struct!(pub PyFrameObject);
Loading