Add more eval functions to c-api (#8244)

This commit is contained in:
Bas Schoenmaeckers authored and GitHub committed 2026-07-09 14:14:56 +09:00
1 parent bf98131551
commit d3f0729fdf
3 files changed
+121 -13

No files matched your search

+88 -1
View File
@@ -1,3 +1,4 @@
use crate::pyframe::PyFrameObject;
use crate::pystate::with_vm;
use crate::unicodeobject::decode_fsdefault_and_size;
use core::ffi::{CStr, c_char, c_int};
@@ -5,8 +6,8 @@ use core::ptr::NonNull;
use rustpython_vm::builtins::{PyCode, PyDict};
use rustpython_vm::function::ArgMapping;
use rustpython_vm::scope::Scope;
use rustpython_vm::version;
use rustpython_vm::{AsObject, PyObject, TryFromObject};
use rustpython_vm::{PyObjectRef, version};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn Py_CompileString(
@@ -42,6 +43,16 @@ pub unsafe extern "C" fn PyEval_EvalCode(
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyEval_EvalFrame(f: *mut PyFrameObject) -> *mut PyObject {
unsafe { PyEval_EvalFrameEx(f, 0) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyEval_EvalFrameEx(f: *mut PyFrameObject, _exc: c_int) -> *mut PyObject {
with_vm(|vm| vm.run_frame(unsafe { &*f }.to_owned()))
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetBuiltins() -> *mut PyObject {
with_vm(|vm| {
@@ -52,6 +63,82 @@ pub extern "C" fn PyEval_GetBuiltins() -> *mut PyObject {
})
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetFrame() -> *mut PyFrameObject {
with_vm(|vm| -> *mut PyObject {
vm.current_frame()
.map(|frame| frame.as_object().as_raw().cast_mut())
.unwrap_or_default()
})
.cast()
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetFrameBuiltins() -> *mut PyObject {
with_vm(|vm| {
vm.current_frame().map_or_else(
|| vm.builtins.as_object().to_owned(),
|frame| frame.builtins.as_object().to_owned(),
)
})
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetFrameGlobals() -> *mut PyObject {
with_vm(|vm| {
vm.current_frame()
.map(|frame| frame.globals.as_object().to_owned().into_raw().as_ptr())
.unwrap_or_default()
})
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetFrameLocals() -> *mut PyObject {
with_vm(|vm| {
let Some(frame) = vm.current_frame() else {
return Ok(core::ptr::null_mut());
};
let locals: PyObjectRef = frame.locals(vm)?.into();
Ok(locals.into_raw().as_ptr())
})
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetGlobals() -> *mut PyObject {
with_vm(|vm| {
vm.current_frame()
.map(|frame| frame.globals.as_object().as_raw())
.unwrap_or_default()
})
}
#[unsafe(no_mangle)]
pub extern "C" fn PyEval_GetLocals() -> *mut PyObject {
with_vm(|vm| {
let Some(frame) = vm.current_frame() else {
return Ok(core::ptr::null_mut());
};
let _ = frame.locals(vm)?;
Ok(frame.locals.as_object(vm).as_raw().cast_mut())
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyEval_GetFuncDesc(func: *mut PyObject) -> *const c_char {
with_vm(|vm| {
let func = unsafe { &*func };
let cls = func.class();
if cls.is(vm.ctx.types.bound_method_type)
|| cls.is(vm.ctx.types.function_type)
|| cls.is(vm.ctx.types.builtin_function_or_method_type)
{
c"()"
} else {
c" object"
}
})
}
#[cfg(test)]
mod tests {
use pyo3::exceptions::PyException;
+12 -10
View File
@@ -1,19 +1,21 @@
use crate::PyObject;
use crate::pystate::with_vm;
use core::ffi::c_int;
use rustpython_vm::Py;
use rustpython_vm::builtins::PyCode;
use rustpython_vm::frame::Frame;
pub type PyFrameObject = Py<Frame>;
pub type PyCodeObject = Py<PyCode>;
#[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::<Frame>(vm)?;
Ok(frame.f_code())
})
pub unsafe extern "C" fn PyFrame_GetCode(frame: *mut PyFrameObject) -> *mut PyCodeObject {
with_vm(|_vm| Ok(unsafe { &*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::<Frame>(vm)?;
Ok(frame.f_lineno() as core::ffi::c_int)
pub unsafe extern "C" fn PyFrame_GetLineNumber(frame: *mut PyFrameObject) -> c_int {
with_vm(|_vm| {
let lineno = unsafe { &*frame }.f_lineno();
Ok(lineno.try_into().unwrap_or(c_int::MAX))
})
}
+21 -2
View File
@@ -1,7 +1,7 @@
use crate::PyObject;
use core::convert::Infallible;
use core::ffi::{c_char, c_double, c_int, c_long, c_ulong, c_void};
use rustpython_vm::{PyObjectRef, PyRef, PyResult, VirtualMachine};
use core::ffi::{CStr, c_char, c_double, c_int, c_long, c_ulong, c_void};
use rustpython_vm::{Py, PyObjectRef, PyRef, PyResult, VirtualMachine};
pub(crate) trait FfiResult<Output = Self> {
const ERR_VALUE: Output;
@@ -36,6 +36,17 @@ where
}
}
impl<T> FfiResult<*mut Py<T>> for PyRef<T>
where
Self: Into<PyObjectRef>,
{
const ERR_VALUE: *mut Py<T> = core::ptr::null_mut();
fn into_output(self, _vm: &VirtualMachine) -> *mut Py<T> {
self.into().into_raw().as_ptr().cast()
}
}
impl FfiResult<*mut PyObject> for PyObjectRef {
const ERR_VALUE: *mut PyObject = core::ptr::null_mut();
@@ -92,6 +103,14 @@ impl FfiResult for *const c_char {
}
}
impl FfiResult<*const c_char> for &CStr {
const ERR_VALUE: *const c_char = core::ptr::null_mut();
fn into_output(self, _vm: &VirtualMachine) -> *const c_char {
self.as_ptr()
}
}
impl FfiResult<isize> for usize {
const ERR_VALUE: isize = -1;