Skip to content

Commit d3f0729

Browse files
Add more eval functions to c-api (#8244)
1 parent bf98131 commit d3f0729

3 files changed

Lines changed: 121 additions & 13 deletions

File tree

crates/capi/src/ceval.rs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
use crate::pyframe::PyFrameObject;
12
use crate::pystate::with_vm;
23
use crate::unicodeobject::decode_fsdefault_and_size;
34
use core::ffi::{CStr, c_char, c_int};
45
use core::ptr::NonNull;
56
use rustpython_vm::builtins::{PyCode, PyDict};
67
use rustpython_vm::function::ArgMapping;
78
use rustpython_vm::scope::Scope;
8-
use rustpython_vm::version;
99
use rustpython_vm::{AsObject, PyObject, TryFromObject};
10+
use rustpython_vm::{PyObjectRef, version};
1011

1112
#[unsafe(no_mangle)]
1213
pub unsafe extern "C" fn Py_CompileString(
@@ -42,6 +43,16 @@ pub unsafe extern "C" fn PyEval_EvalCode(
4243
})
4344
}
4445

46+
#[unsafe(no_mangle)]
47+
pub unsafe extern "C" fn PyEval_EvalFrame(f: *mut PyFrameObject) -> *mut PyObject {
48+
unsafe { PyEval_EvalFrameEx(f, 0) }
49+
}
50+
51+
#[unsafe(no_mangle)]
52+
pub unsafe extern "C" fn PyEval_EvalFrameEx(f: *mut PyFrameObject, _exc: c_int) -> *mut PyObject {
53+
with_vm(|vm| vm.run_frame(unsafe { &*f }.to_owned()))
54+
}
55+
4556
#[unsafe(no_mangle)]
4657
pub extern "C" fn PyEval_GetBuiltins() -> *mut PyObject {
4758
with_vm(|vm| {
@@ -52,6 +63,82 @@ pub extern "C" fn PyEval_GetBuiltins() -> *mut PyObject {
5263
})
5364
}
5465

66+
#[unsafe(no_mangle)]
67+
pub extern "C" fn PyEval_GetFrame() -> *mut PyFrameObject {
68+
with_vm(|vm| -> *mut PyObject {
69+
vm.current_frame()
70+
.map(|frame| frame.as_object().as_raw().cast_mut())
71+
.unwrap_or_default()
72+
})
73+
.cast()
74+
}
75+
76+
#[unsafe(no_mangle)]
77+
pub extern "C" fn PyEval_GetFrameBuiltins() -> *mut PyObject {
78+
with_vm(|vm| {
79+
vm.current_frame().map_or_else(
80+
|| vm.builtins.as_object().to_owned(),
81+
|frame| frame.builtins.as_object().to_owned(),
82+
)
83+
})
84+
}
85+
86+
#[unsafe(no_mangle)]
87+
pub extern "C" fn PyEval_GetFrameGlobals() -> *mut PyObject {
88+
with_vm(|vm| {
89+
vm.current_frame()
90+
.map(|frame| frame.globals.as_object().to_owned().into_raw().as_ptr())
91+
.unwrap_or_default()
92+
})
93+
}
94+
95+
#[unsafe(no_mangle)]
96+
pub extern "C" fn PyEval_GetFrameLocals() -> *mut PyObject {
97+
with_vm(|vm| {
98+
let Some(frame) = vm.current_frame() else {
99+
return Ok(core::ptr::null_mut());
100+
};
101+
let locals: PyObjectRef = frame.locals(vm)?.into();
102+
Ok(locals.into_raw().as_ptr())
103+
})
104+
}
105+
106+
#[unsafe(no_mangle)]
107+
pub extern "C" fn PyEval_GetGlobals() -> *mut PyObject {
108+
with_vm(|vm| {
109+
vm.current_frame()
110+
.map(|frame| frame.globals.as_object().as_raw())
111+
.unwrap_or_default()
112+
})
113+
}
114+
115+
#[unsafe(no_mangle)]
116+
pub extern "C" fn PyEval_GetLocals() -> *mut PyObject {
117+
with_vm(|vm| {
118+
let Some(frame) = vm.current_frame() else {
119+
return Ok(core::ptr::null_mut());
120+
};
121+
let _ = frame.locals(vm)?;
122+
Ok(frame.locals.as_object(vm).as_raw().cast_mut())
123+
})
124+
}
125+
126+
#[unsafe(no_mangle)]
127+
pub unsafe extern "C" fn PyEval_GetFuncDesc(func: *mut PyObject) -> *const c_char {
128+
with_vm(|vm| {
129+
let func = unsafe { &*func };
130+
let cls = func.class();
131+
if cls.is(vm.ctx.types.bound_method_type)
132+
|| cls.is(vm.ctx.types.function_type)
133+
|| cls.is(vm.ctx.types.builtin_function_or_method_type)
134+
{
135+
c"()"
136+
} else {
137+
c" object"
138+
}
139+
})
140+
}
141+
55142
#[cfg(test)]
56143
mod tests {
57144
use pyo3::exceptions::PyException;

crates/capi/src/pyframe.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
use crate::PyObject;
21
use crate::pystate::with_vm;
2+
use core::ffi::c_int;
3+
use rustpython_vm::Py;
4+
use rustpython_vm::builtins::PyCode;
35
use rustpython_vm::frame::Frame;
46

7+
pub type PyFrameObject = Py<Frame>;
8+
pub type PyCodeObject = Py<PyCode>;
9+
510
#[unsafe(no_mangle)]
6-
pub unsafe extern "C" fn PyFrame_GetCode(frame: *mut PyObject) -> *mut PyObject {
7-
with_vm(|vm| {
8-
let frame = unsafe { &*frame }.try_downcast_ref::<Frame>(vm)?;
9-
Ok(frame.f_code())
10-
})
11+
pub unsafe extern "C" fn PyFrame_GetCode(frame: *mut PyFrameObject) -> *mut PyCodeObject {
12+
with_vm(|_vm| Ok(unsafe { &*frame }.f_code()))
1113
}
1214

1315
#[unsafe(no_mangle)]
14-
pub unsafe extern "C" fn PyFrame_GetLineNumber(frame: *mut PyObject) -> core::ffi::c_int {
15-
with_vm(|vm| {
16-
let frame = unsafe { &*frame }.try_downcast_ref::<Frame>(vm)?;
17-
Ok(frame.f_lineno() as core::ffi::c_int)
16+
pub unsafe extern "C" fn PyFrame_GetLineNumber(frame: *mut PyFrameObject) -> c_int {
17+
with_vm(|_vm| {
18+
let lineno = unsafe { &*frame }.f_lineno();
19+
Ok(lineno.try_into().unwrap_or(c_int::MAX))
1820
})
1921
}

crates/capi/src/util.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::PyObject;
22
use core::convert::Infallible;
3-
use core::ffi::{c_char, c_double, c_int, c_long, c_ulong, c_void};
4-
use rustpython_vm::{PyObjectRef, PyRef, PyResult, VirtualMachine};
3+
use core::ffi::{CStr, c_char, c_double, c_int, c_long, c_ulong, c_void};
4+
use rustpython_vm::{Py, PyObjectRef, PyRef, PyResult, VirtualMachine};
55

66
pub(crate) trait FfiResult<Output = Self> {
77
const ERR_VALUE: Output;
@@ -36,6 +36,17 @@ where
3636
}
3737
}
3838

39+
impl<T> FfiResult<*mut Py<T>> for PyRef<T>
40+
where
41+
Self: Into<PyObjectRef>,
42+
{
43+
const ERR_VALUE: *mut Py<T> = core::ptr::null_mut();
44+
45+
fn into_output(self, _vm: &VirtualMachine) -> *mut Py<T> {
46+
self.into().into_raw().as_ptr().cast()
47+
}
48+
}
49+
3950
impl FfiResult<*mut PyObject> for PyObjectRef {
4051
const ERR_VALUE: *mut PyObject = core::ptr::null_mut();
4152

@@ -92,6 +103,14 @@ impl FfiResult for *const c_char {
92103
}
93104
}
94105

106+
impl FfiResult<*const c_char> for &CStr {
107+
const ERR_VALUE: *const c_char = core::ptr::null_mut();
108+
109+
fn into_output(self, _vm: &VirtualMachine) -> *const c_char {
110+
self.as_ptr()
111+
}
112+
}
113+
95114
impl FfiResult<isize> for usize {
96115
const ERR_VALUE: isize = -1;
97116

0 commit comments

Comments
 (0)