Setup:
cargo init --lib
(from within a folder you created)
If you want to support OSX:
.cargo/config
[target.x86_64-apple-darwin]
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
Dependencies:
Cargo.toml
:
[package]
name = "mypackage"
version = "0.1.0"
authors = ["Me <me@domain.com>"]
edition = "2018"
[lib]
name = "pymod"
crate-type = ["cdylib"]
[dependencies]
[dependencies.pyo3]
version = "0.7.0"
features = ["extension-module"]
At this point, cargo build
should already produce a pymod.dll/so/dylib
in target/debug
.
Now we need some actual code so we can play with it in python.
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use pyo3::exceptions;
// #[pyclass] tells pyo3 that this should be treated as a python class
#[pyclass]
struct Vehicle {
#[pyo3(get, set)]
model: String,
#[pyo3(get, set)]
manufacturer: String,
#[pyo3(get, set)]
range: f32,
#[pyo3(get, set)]
price: i32
}
// This macro tells pyo3 that this function is accessible from python
#[pyfunction]
fn vehicles() -> PyResult<Vec<Vehicle>> {
// Let's keep it simple: a vec to hold our vehicles
let mut vehicles = vec![];
vehicles.push(Vehicle {
model: "Model S".to_string(),
manufacturer: "Tesla".to_string(),
range: 520.0,
price: 81980
});
vehicles.push(Vehicle {
model: "Leaf".to_string(),
manufacturer: "Nissan".to_string(),
range: 172.0,
price: 36800
});
vehicles.push(Vehicle {
model: "Urban".to_string(),
manufacturer: "Desiknio".to_string(),
range: 100.0,
price: 3790
});
Ok(vehicles) //return positive PyResult
//If you want exceptions, use PyErr with the pyo3::exceptions already provided for you
//Err(PyErr::new::<exceptions::IOError, _>("Can't open ffproj"))
}
//The name of this function has to match our [lib] name in Cargo.toml
#[pymodule]
fn pymod(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(vehicles))?;
Ok(())
}
now just copy pymod.dylib
to pymod.so
on mac, on windows pymod.dll
to pymod.pyd
and on linux pymod.so
to pymod.so
.
In python:
import pymod
for vehicle in pymod.vehicles():
print(vehicle.manufacturer, vehicle.model, "\n\tEuro / KM:", round(vehicle.price/vehicle.range))
Here are the pyo3 docs: