genghiskhan
genghiskhan

Reputation: 1149

PyO3 pass mutable rust struct between Rust and Python callbacks

I am trying to use Python as a scripting engine for my Rust project. I have some Rust code which calls a Python function which in turn should call some Rust functions. The problem is that there is mutable state that I need to keep track of in Rust-land.

The way I have it set up right now is that Descriptor::eval calls the python

impl Descriptor {
    ...
    fn eval(&self, &PyRefMut<Context>) -> String {
        Python::with_gil(|py| {
            // inner is a Py<PyAny>
            self.inner.call_method(py, "to_string", (ctx,), None)
                .unwrap()
                .downcast_bound::<PyString>(py)
                .unwrap()
                .to_str()
                .unwrap()
                .to_string()
        })
    }
}

The python then calls back into the Rust:

class Class(object):
    @staticmethod
    def to_string(ctx):
        return rust.eval_template(ctx, '$foo')
#[pyfunction]
fn eval_template(mut ctx: PyRefMut<ReprContext>, s: &str) -> String {
    // do stuff with s and ctx
}

The problem is that when the python code tries to call rust.eval_template, the dynamic borrow checker says that ctx is already borrowed.

What I'm guessing is happening is that call_method borrows ctx and since rust.eval_template is called before that function returns, eval_template then also tries to borrow ctx. Though I'm a bit unclear as to what is happening on the whole.

Upvotes: 2

Views: 105

Answers (0)

Related Questions