How to understand Python::with_gil
and Py<Myclass>
?
#2255
-
Q1. With code below I found somthing that if I want to call a python method in Rust, I don't need to add I think maybe because I call the method from python side which means I already got the gil, so I do not need to add #[pyclass]
pub struct Myclass {
pycls: Py<PyAny>,
}
#[pymethods]
impl Myclass {
#[new]
pub fn new(pycls: Py<PyAny>) -> Self {
Myclass { pycls }
}
pub fn on_calculation(&mut self, py:Python) {
let py_model = self.pycls.as_ref(py);
py_model
.call_method("on_calculation", (), None)
.unwrap();
// This also work!!!!!!
// Python::with_gil(|py| {
// let py_model = self.pycls.as_ref(py);
// py_model
// .call_method("on_calculation", (), None)
// .unwrap();
// });
}
#[pyclass]
pub struct Player {
cls: Myclass,
}
#[pymethods]
impl Player {
#[new]
pub fn new(cls: Myclass) -> Self {
Player { cls: cls}
}
pub fn run(&mut self, num:i64, py: Python) {
for _i in 0..num {
self.cls.on_calculation(py);
}
}
} class TestContext:
def __init__(self, num: int):
self.x = num
def on_calculation(self):
self.x += 3
if __name__=="__main__":
pycls = TestContext(9)
rcls = Myclass(pycls)
x = Player(rcls)
x.run(10) Q2. I found if replace the member #[pymethods]
impl Player {
#[new]
pub fn new(cls: Py<Myclass>) -> Self {
Player { cls:cls }
}
pub fn run(&mut self, num:i64, py: Python) {
for _i in 0..num {
self.cls.as_ref(py).call_method("on_calculation", (), None).unwrap();
}
}
} How to understand this and what's the difference in these two call method? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
A value
Methods exposed as Finally, Additionally, a constructor like #[new]
pub fn new(cls: Myclass) -> Self {
Player { cls: cls}
} should not be callable from Python at all if |
Beta Was this translation helpful? Give feedback.
A value
py: Python<'a>
is a proof that the GIL is held, i.e. all functions which require you to have the GIL express this by requiring you to pass such apy: Python<'a>
token as an argument. One example isPy::as_ref
which produces a reference into the Python heap which is valid as long as the GIL is held, i.e. its lifetime'a
is bound to that of the token.Python::with_gil
is a function to acquire the GIL, i.e. it will check whether the GIL is already held, lock it if not and depending on that also release it before returning. In this way, it is a safe method to produce such apy: Python<'a>
token.Methods exposed as
#[pymethods]
are supposed to be called from Python meaning that the GIL…