mbfernan
mbfernan

Reputation: 13

Exposing Python class to Rust

I'm trying to do a simple task of handling a Python class in Rust. Instantiate it, do an operation and than access one of its members. I extensively looked at PyO3 and cpython documentation and they cover a lot of the opposite (calling Rust from Python).

Why in the code below the application cannot find the attributes?

Python side:

class Vehicle:
    def __init__(self) -> None:
        self.speed = 0

    def increase(self):
        self.speed += 1
    
    def get_speed(self):
        return self.speed

Rust side:

extern crate pyo3;    
use pyo3::prelude::*;

fn main()  -> PyResult<()> {
    pyo3::prepare_freethreaded_python();
    
    Python::with_gil(|py| {
        let builtins = PyModule::import(py, "vehicle")?;
        builtins.getattr("increase")?.call0()?;
        println!("{}", builtins.getattr("get_speed")?.call0()?);
        Ok(())
    })
}

I'm following PyO3 documentation and here is the output:

Error: PyErr { type: <class 'AttributeError'>, value: AttributeError("module 'vehicle' has no attribute 'increase'"), traceback: None }
error: process didn't exit successfully: `target\debug\test_ffi.exe` (exit code: 1)

The expected output would be:

1

Upvotes: 0

Views: 558

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 70860

builtins contains the vehicle module. You need to retrieve the Vehicle class and instantiate it:

Python::with_gil(|py| {
    let builtins = PyModule::import(py, "vehicle")?;
    let vehicle = builtins.getattr("Vehicle")?.call0()?;
    vehicle.getattr("increase")?.call0()?;
    println!("{}", vehicle.getattr("get_speed")?.call0()?);
    Ok(())
})

Upvotes: 3

Related Questions