This is Call Rust from Python to speed up! PyO3 Tutorial: Wrapping Classes Part ➀
It will be a continuation of.
The goal,
Define a Rust class (struct + method) and call it from Python
It was,
Last time I explained how to call a class written in Rust from Python.
The class constructor and the property getter, setter could also be called from Python via PyO3.
This time, I'll add some class methods and explain how to convert from Rust to Python type via PyO3.
See ** PyO3's git repository ** (here),
I will explain how to pass a Rust object to the Python side with PyO3.
Vec -> ListHashmap -> DictVec -> TupleEtc.
Use the project created by cargo new --lib example up to the last time.
Of course, there is no problem even if you make a new one.
As a recap, last time I made it possible to call the getter and setter of the class constructor and property num from Python via PyO3.
Below is the code I completed last time.
//lib.rs
use pyo3::prelude::*;
use pyo3::{wrap_pyfunction};
// ======================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,
}
#[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(())
}
}
// =================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(())
}
This time, we will add 6 functions to this MyClass.
Immediately, the following is the code.
//lib.rs
use pyo3::types::PyType;
use pyo3::types::PyInt;
use pyo3::types::PyList;
use pyo3::types::PyTuple;
use pyo3::types::PyDateTime;
use std::collections::HashMap;
#[pymethods]
impl MyClass{
fn test1(&self) -> PyResult<bool>{
if self.num > 3{
Ok(true)
}else{
Ok(false)
}
}
fn test2(&self) -> PyResult<String>{
if self.debug == true{
let result: &str = "your debug is True";
Ok(result.to_string())
}else{
let result: &str = "your debug is False";
Ok(result.to_string())
}
}
fn test3<'py>(&self, py: Python<'py>) -> PyResult<&'py PyList>{
let mut vec = vec![1,2,3];
let result = PyList::new(py, &vec);
Ok(result)
}
fn test4(&self, py: Python) -> PyResult<PyObject>{
let mut map = HashMap::new();
map.insert("key1", 1);
map.insert("key2", 2);
map.insert("key3", 3);
assert_eq!(map["key1"], 1);
assert_eq!(map["key2"], 2);
assert_eq!(map["key3"], 3);
Ok(map.to_object(py))
}
fn test5(&self) -> PyResult<f64>{
let result:f64 = 1.23;
Ok(result)
}
fn test6<'py>(&self, py: Python<'py>, dt: &PyDateTime) -> PyResult<&'py PyTuple>{
let mut vec = vec![3,4,5];
let result = PyTuple::new(py, &vec);
Ok(result)
}
}
fn test1
Passing Rust bool to Python bool via PyO3.
fn test2
I'm passing a Rust String to a Python str via PyO3.
fn test3
Passing Rust's Vec to Python's List via PyO3.
I don't understand how to write this. ..
fn test4
I'm passing the Rust Hashmap to the Python Dict via PyO3.
fn test5
Passing Rust's f64 to Python's float via PyO3.
fn test6
Passing Rust's Vec to Python's tuple via PyO3. At this time, Python Datetime is received as an argument of the function.
I don't understand how to write this. ..
Regarding test3 and test6, I don't understand how to write honestly, but I will execute the test.
By preparing Cargo.toml and setup.py as before,
python setup.py install
You can build with.
Then prepare test.py as follows and run the test.
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)
result = test.test1()
print(result)
print(type(result))
result = test.test2()
print(result)
print(type(result))
result = test.test3()
print(result)
print(type(result))
result = test.test4()
print(result)
print(type(result))
result = test.test5()
print(result)
print(type(result))
import datetime
now = datetime.datetime.now()
result = test.test6(now)
print(result)
print(type(result))
This time, I added some class methods and explained how to convert from Rust to Python type via PyO3.
Although it feels relatively easier to understand than Cython, the version of PyO3 itself is being updated steadily, so the best thing is to develop it with the version in mind (Fix).
Or you should follow Git properly and pay attention to the change of API name.
However, Rust is interesting, so I will continue to study.
This time around here.
end.
Recommended Posts