-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Open
Labels
C-bugSomething isn't workingSomething isn't working
Description
🧪 Problem 1: PyPayload
Causes Runtime Panic
When I define a custom Rust structure with #[derive(PyPayload)]
and use it in combination with RustPython, calling the following Python code results in a crash:
Python code
from rust_py_module import Base, Wda, image, test
import time
import sys
import io
def python_callback():
test.test()
Rust code
pub fn main() {
let interp = rustpython::InterpreterConfig::new()
.init_stdlib()
.init_hook(Box::new(|vm| {
vm.add_native_module(
"rust_py_module".to_owned(),
Box::new(rust_py_module::make_module),
);
}))
.interpreter();
interp.enter(|vm| {
vm.insert_sys_path(vm.new_pyobj(r"C:\Users\RustroverProjects\python\examples"))
.expect("add path");
let module = match vm.import("call_between_rust_and_python", 0) {
Ok(module) => module,
Err(exc) => {
let mut error_output = String::new();
if let Err(_) = vm.write_exception(&mut error_output, &exc) {
println!("");
} else {
println!("{}", error_output);
}
panic!()
}
};
let take_string_fn = module.get_attr("python_callback", vm).unwrap();
match take_string_fn.call((), vm) {
Ok(result) => {
println!(": {:?}", result);
}
Err(exc) => {
let mut error_output = String::new();
if let Err(_) = vm.write_exception(&mut error_output, &exc) {
println!("");
} else {
println!("{}", error_output);
}
}
}
})
}
#[pymodule]
mod rust_py_module {
use std::mem::ManuallyDrop;
use super::*;
use rustpython::vm::{builtins::PyList, convert::ToPyObject, PyObjectRef};
use rustpython_vm::builtins::PyTypeRef;
use rustpython_vm::FromArgs;
use rustpython_vm::types::Constructor;
use rustpython_vm::PyRef;
use crate::image::{feature_config, DetectorParams, FeatureDetector, SiftParams, SIFT_MODE};
#[pyattr]
#[pyclass(module = "rust_py_module", name = "test")]
#[derive(Debug, PyPayload)]
struct Test;
impl Constructor for Test {
type Args = ();
fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
let rust_struct = Test ;
rust_struct.into_ref_with_type(vm, cls).map(Into::into)
}
}
#[pyclass(with(Constructor))]
impl Test {
#[pymethod]
fn test() -> PyResult<crate::feature_config1> {
Ok(crate::feature_config1::new())
}
}
}
Custom Class
#[rustpython_vm::pyclass(module = false, name = "feature_config")]
#[repr(C)]
#[derive(Debug, PyPayload)]
pub struct feature_config1 {
pub text: String
}
#[rustpython_vm::pyclass]
impl feature_config1 {
pub fn new() -> Self {
Self { text: String::from("a") }
}
}
Panic Error
static type has not been initialized. e.g. the native types defined in different module may be used before importing library.
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library\std\src/panicking.rs:697:5
1: core::panicking::panic_fmt
at /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library\core\src/panicking.rs:75:14
2: core::option::expect_failed
at /rustc/6b00bc3880198600130e1cf62b8f8a93494488cc/library\core\src/panicking.rs:269:5
3: core::option::Option<T>::expect
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\core\src\option.rs:958:21
4: rustpython_vm::class::StaticType::static_type
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\class.rs:23:9
5: <python::feature_config1 as rustpython_vm::object::payload::PyPayload>::class
at .\src\main.rs:267:17
6: rustpython_vm::object::payload::PyPayload::into_ref
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\object\payload.rs:49:19
7: rustpython_vm::object::payload::PyPayload::into_pyobject
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\object\payload.rs:26:9
8: rustpython_vm::object::ext::<impl rustpython_vm::convert::to_pyobject::ToPyObject for T>::to_pyobject
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\object\ext.rs:563:9
9: rustpython_vm::object::ext::<impl rustpython_vm::convert::to_pyobject::ToPyResult for core::result::Result<T,E>>::to_pyresult::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\object\ext.rs:584:24
10: core::result::Result<T,E>::map
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\core\src\result.rs:801:25
11: rustpython_vm::object::ext::<impl rustpython_vm::convert::to_pyobject::ToPyResult for core::result::Result<T,E>>::to_pyresult
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\object\ext.rs:584:9
12: rustpython_vm::function::builtin::<impl rustpython_vm::function::builtin::sealed::PyNativeFnInternal<(),R,()> for F>::call_
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\function\builtin.rs:172:17
13: <F as rustpython_vm::function::builtin::IntoPyNativeFn<(T,R,VM)>>::call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\function\builtin.rs:97:9
14: rustpython_vm::function::builtin::into_func::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\function\builtin.rs:50:38
15: <rustpython_vm::builtins::descriptor::PyMethodDescriptor as rustpython_vm::types::slot::Callable>::call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\builtins\descriptor.rs:97:9
16: rustpython_vm::types::slot::Callable::slot_call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\types\slot.rs:868:9
17: rustpython_vm::protocol::callable::PyCallable::invoke
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\protocol\callable.rs:51:22
18: rustpython_vm::protocol::callable::<impl rustpython_vm::object::core::PyObject>::call_with_args
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\protocol\callable.rs:33:9
19: rustpython_vm::protocol::callable::<impl rustpython_vm::object::core::PyObject>::call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\protocol\callable.rs:22:9
20: rustpython_vm::frame::ExecutingFrame::execute_method_call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\frame.rs:1504:21
21: rustpython_vm::frame::ExecutingFrame::execute_instruction
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\frame.rs:1093:17
22: rustpython_vm::frame::ExecutingFrame::run
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\frame.rs:362:26
23: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::run::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\frame.rs:242:35
24: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::with_exec
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\frame.rs:237:9
25: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::run
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\frame.rs:242:9
26: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\mod.rs:424:42
27: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\mod.rs:452:26
28: rustpython_vm::vm::VirtualMachine::with_recursion
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\mod.rs:440:22
29: rustpython_vm::vm::VirtualMachine::with_frame
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\mod.rs:450:9
30: rustpython_vm::vm::VirtualMachine::run_frame
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\mod.rs:424:15
31: rustpython_vm::builtins::function::PyFunction::invoke_with_locals
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\builtins\function.rs:338:31
32: rustpython_vm::builtins::function::PyFunction::invoke
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\builtins\function.rs:344:9
33: <rustpython_vm::builtins::function::PyFunction as rustpython_vm::types::slot::Callable>::call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\builtins\function.rs:492:9
34: rustpython_vm::types::slot::Callable::slot_call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\types\slot.rs:868:9
35: rustpython_vm::protocol::callable::PyCallable::invoke
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\protocol\callable.rs:51:22
36: rustpython_vm::protocol::callable::<impl rustpython_vm::object::core::PyObject>::call_with_args
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\protocol\callable.rs:33:9
37: rustpython_vm::protocol::callable::<impl rustpython_vm::object::core::PyObject>::call
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\protocol\callable.rs:22:9
38: python::main::{{closure}}
at .\src\main.rs:242:15
39: rustpython_vm::vm::interpreter::Interpreter::enter::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\interpreter.rs:72:39
40: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\core\src\panic\unwind_safe.rs:272:9
41: std::panicking::try::do_call
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\std\src\panicking.rs:589:40
42: __rust_try
43: std::panicking::try
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\std\src\panicking.rs:552:19
44: std::panic::catch_unwind
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\std\src\panic.rs:359:14
45: rustpython_vm::vm::thread::enter_vm::{{closure}}
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\thread.rs:31:19
46: std::thread::local::LocalKey<T>::try_with
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\std\src\thread\local.rs:315:12
47: std::thread::local::LocalKey<T>::with
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\std\src\thread\local.rs:279:15
48: rustpython_vm::vm::thread::enter_vm
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\thread.rs:28:5
49: rustpython_vm::vm::interpreter::Interpreter::enter
at C:\Users\35600\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\rustpython-vm-0.4.0\src\vm\interpreter.rs:72:9
50: python::main
at .\src\main.rs:200:5
51: core::ops::function::FnOnce::call_once
at C:\Users\35600\.rustup\toolchains\stable-x86_64-pc-windows-gnu\lib/rustlib/src/rust\library\core\src\ops\function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\python.exe` (exit code: 101)
However, if I manually implement PyPayload
, like this, the error is gone:
impl PyPayload for feature_config1 {
fn class(ctx: &Context) -> &'static Py<PyType> {
ctx.types.object_type
}
}
So the issue seems to be that #[derive(PyPayload)]
fails to properly register the static type when used in this context.
🧪 Problem 2: Cannot Call Methods on Returned Custom Object
When I add a method to feature_config1
, I cannot call it from Python:
#[rustpython_vm::pyclass]
impl feature_config1 {
pub fn new() -> Self {
Self { text: String::from("a") }
}
#[pymethod]
pub fn t(&self) {
println!("t");
}
}
Calling:
test.test().t()
results in:
Traceback (most recent call last):
File "C:\Users\\35600\RustroverProjects\python\examples\call_between_rust_and_python.py", line 8, in python_callback
test.test().t()
AttributeError: 'object' object has no attribute 't'
But I expected test()
to return a feature_config1
instance and be able to call its methods. If I did anything wrong, please let me know how to correctly expose and use custom objects with methods in Python via RustPython.
Thanks in advance!
Metadata
Metadata
Assignees
Labels
C-bugSomething isn't workingSomething isn't working