diff --git a/.cspell.dict/cpython.txt b/.cspell.dict/cpython.txt
index 47ec7dd60c8..64a2e7479fc 100644
--- a/.cspell.dict/cpython.txt
+++ b/.cspell.dict/cpython.txt
@@ -191,6 +191,7 @@ pycore
pyinner
pydecimal
pyerrors
+pyframe
Pyfunc
pylifecycle
pymain
diff --git a/crates/capi/src/lib.rs b/crates/capi/src/lib.rs
index eba7de2786d..15632648961 100644
--- a/crates/capi/src/lib.rs
+++ b/crates/capi/src/lib.rs
@@ -28,6 +28,7 @@ pub mod object;
pub mod osmodule;
pub mod pycapsule;
pub mod pyerrors;
+pub mod pyframe;
pub mod pylifecycle;
pub mod pymem;
pub mod pystate;
diff --git a/crates/capi/src/pyframe.rs b/crates/capi/src/pyframe.rs
new file mode 100644
index 00000000000..d8e9d124bb0
--- /dev/null
+++ b/crates/capi/src/pyframe.rs
@@ -0,0 +1,19 @@
+use crate::PyObject;
+use crate::pystate::with_vm;
+use rustpython_vm::frame::Frame;
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn PyFrame_GetCode(frame: *mut PyObject) -> *mut PyObject {
+ with_vm(|vm| {
+ let frame = unsafe { &*frame }.try_downcast_ref::(vm)?;
+ Ok(frame.f_code())
+ })
+}
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn PyFrame_GetLineNumber(frame: *mut PyObject) -> core::ffi::c_int {
+ with_vm(|vm| {
+ let frame = unsafe { &*frame }.try_downcast_ref::(vm)?;
+ Ok(frame.f_lineno() as core::ffi::c_int)
+ })
+}