This is Call Rust from Python to speed it up! PyO3 Tutorial: Wrapping a Simple Function Part ➁
It will be a continuation of.
Define a Rust class (struct + method) and call it from Python
The goal is that.
This time, I will explain how to parse a class and how to call getters and setters via PyO3.
Use the project you created last time with cargo new --lib example
.
Of course, there is no problem even if you make a new one.
Write the following in lib.rs
.
//lib.rs
use pyo3::prelude::*;
// ======================RUST CLASS TO PYTHON ======================================
/// Class for demonstration
// this class, MyClass can be called from python
#[pyclass(module = "my_class")]
struct MyClass {
num: i32,
debug: bool,
}
here,
#[pyclass(module = "my_class")]
Allows you to call from Python via PyO3. I wrote (module =" my_class ")
as a spell, but I don't really understand what it means. I'm sorry.
Here, MyClass
is defined as Struct
and as a property
It has num: i32
and debug: bool
.
First, write a constructor so that you can call this class as a Python object.
#[pymethods]
impl MyClass{
#[new]
fn new(num:i32, debug:bool) -> Self{
MyClass{
num: num,
debug: debug
}
}
Here, on top of ʻimpl`
#[pymethods]
Is declared (decorated?),
Also above the fn new (num: i32, debug: bool)
that shows the constructor
#[new]
Note that it has been declared.
Add this to the module as in the previous function:
//lib.rs
use pyo3::{wrap_pyfunction};
// =================CREATING MODULE FOR PYTHON=========================
/// This module is a python module implemented in Rust.
#[pymodule]
fn test_library(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(get_prime_numbers))?;
m.add_class::<MyClass>()?;
Ok(())
}
here,
m.add_class::<MyClass>()?;
Line adds MyClass to the module.
This time, in addition to the class declaration, I will write the property getter and setter so that they can be called from Python.
//lib.rs
#[pymethods]
impl MyClass{
#[new]
fn new(num:i32, debug:bool) -> Self{
MyClass{
num: num,
debug: debug
}
}
#[getter]
fn get_num(&self) -> PyResult<i32>{
Ok(self.num)
}
#[setter]
fn set_num(&mut self, num: i32) -> PyResult<()>{
self.num = num;
Ok(())
}
}
In this way, you can also call getters and setters from Python via PyO3 by using the # [getter]
and # [setter]
decorators.
This time I wrote only about the property num
.
Regarding the return value of getter, since the type of num
is ʻi32, the Python side receives it as
PyResult . There is no return value for setter, so you can write
PyResult <()>`.
Both when passing a Python object,
Ok(self.num)
Ok(())
Handing over using is the same as last time.
setup.py
and Cargo.toml
are the same as last time, but just in case,
Cargo.toml
[package]
name = "test"
version = "0.1.0"
edition = "2018"
[lib]
name = "test_library"
crate-type = ["cdylib"]
[dependencies.pyo3]
version = "0.9.1"
features = ["extension-module"]
setup.py
from setuptools import setup
from setuptools_rust import Binding, RustExtension
setup(name='ope_rust',
version='0.1',
rust_extensions=[
RustExtension('ope_rust', 'Cargo.toml',
binding=Binding.PyO3)],
zip_safe=False)
It will be.
python setup.py install
You can compile by doing.
When you run the following test program,
test.py
import test_library
if __name__ == "__main__":
# Testing class
print("\ntest for class")
num = 2
debug = True
test = test_library.MyClass(num=num, debug=debug)
print(test.num) # getter test
test.num = 4 # setter test
print(test.num)
$ python test.py
test for class
2
4
It turns out that we were able to construct the class and execute the get and set properties.
The goal,
Define a Rust class (struct + method) and call it from Python
It was,
This time I explained how to call a class written in Rust from Python.
The class constructor and property getters and setters could also be called from Python via PyO3.
Next time, I'd like to add some methods of the class and explain various type conversions.
This time around here.
end.
Recommended Posts