#numpy #python #binding

nightly numpy

Rust binding of NumPy C-API

7 releases

0.3.2 Sep 6, 2018
0.3.1 Sep 6, 2018
0.3.0 Aug 22, 2018
0.2.1 May 16, 2017
0.1.1 May 11, 2017

#34 in FFI

Download history 1/week @ 2018-08-20 30/week @ 2018-08-27 8/week @ 2018-09-03 29/week @ 2018-09-10 3/week @ 2018-09-17 18/week @ 2018-09-24 36/week @ 2018-10-01 9/week @ 2018-10-08 5/week @ 2018-10-15 94/week @ 2018-10-22 3/week @ 2018-10-29 58/week @ 2018-11-05 69/week @ 2018-11-12

98 downloads per month
Used in 1 crate

Custom license

120KB
2K SLoC

rust-numpy

Build Status Build status Crate

Rust bindings for the NumPy C-API

API documentation

Requirements

Note Starting from 0.3, rust-numpy migrated from rust-cpython to pyo3. If you want to use rust-cpython, use version 0.2.1 from crates.io.

Example

Execute a Python program from Rust and get results

[package]
name = "numpy-test"

[dependencies]
pyo3 = "^0.5.0-alpha.2"
numpy = "0.4.0-alpha.1"
extern crate numpy;
extern crate pyo3;
use numpy::{PyArray1, get_array_module};
use pyo3::prelude::{ObjectProtocol, PyResult, Python};
use pyo3::types::PyDict;

fn main() -> Result<(), ()> {
    let gil = Python::acquire_gil();
    main_(gil.python()).map_err(|e| {
        eprintln!("error! :{:?}", e);
        // we can't display python error type via ::std::fmt::Display
        // so print error here manually
        e.print_and_set_sys_last_vars(gil.python());
    })
}

fn main_<'py>(py: Python<'py>) -> PyResult<()> {
    let np = get_array_module(py)?;
    let dict = PyDict::new(py);
    dict.set_item("np", np)?;
    let pyarray: &PyArray1<i32> = py
        .eval("np.array([1, 2, 3], dtype='int32')", Some(&dict), None)?
        .extract()?;
    let slice = pyarray.as_slice();
    assert_eq!(slice, &[1, 2, 3]);
    Ok(())
}

Write a Python module in Rust

Please see the example directory for a complete example

[lib]
name = "rust_ext"
crate-type = ["cdylib"]

[dependencies]
numpy = "0.4.0-alpha.1"
ndarray = "0.12"

[dependencies.pyo3]
version = "^0.5.0-alpha.2"
features = ["extension-module"]
extern crate ndarray;
extern crate numpy;
extern crate pyo3;

use ndarray::{ArrayD, ArrayViewD, ArrayViewMutD};
use numpy::{IntoPyArray, PyArrayDyn};
use pyo3::prelude::{pymodinit, PyModule, PyResult, Python};

#[pymodinit]
fn rust_ext(_py: Python, m: &PyModule) -> PyResult<()> {
    // immutable example
    fn axpy(a: f64, x: ArrayViewD<f64>, y: ArrayViewD<f64>) -> ArrayD<f64> {
        a * &x + &y
    }

    // mutable example (no return)
    fn mult(a: f64, mut x: ArrayViewMutD<f64>) {
        x *= a;
    }

    // wrapper of `axpy`
    #[pyfn(m, "axpy")]
    fn axpy_py(
        py: Python,
        a: f64,
        x: &PyArrayDyn<f64>,
        y: &PyArrayDyn<f64>,
    ) -> PyResult<PyArrayDyn<f64>> {
        // you can convert numpy error into PyErr via ?
        let x = x.as_array();
        // you can also specify your error context, via closure
        let y = y.as_array();
        Ok(axpy(a, x, y).into_pyarray(py).to_owned(py))
    }

    // wrapper of `mult`
    #[pyfn(m, "mult")]
    fn mult_py(_py: Python, a: f64, x: &PyArrayDyn<f64>) -> PyResult<()> {
        let x = x.as_array_mut();
        mult(a, x);
        Ok(())
    }

    Ok(())
}

Contribution

This project is still in pre-alpha. We need your feedback. Don't hesitate to open issues!

Version

  • v0.4.0(coming soon)

    • Duplicate PyArrayModule and import Numpy API automatically
    • Fix memory leak of IntoPyArray and add ToPyArray crate
    • PyArray has dimension as type parameter. Now it looks like PyArray<T, D>
    • Use ndarray::IntoDimension to specify dimension
  • v0.3.1, v0.3.2

    • Just update dependencies
  • v0.3.0

  • v0.2.1

    • NEW: trait IntoPyErr, IntoPyResult for error translation
  • v0.2.0

    • NEW: traits IntoPyArray, ToPyArray
    • MOD: Interface of PyArray creation functions are changed
  • v0.1.1

    • Update documents
  • v0.1.0

    • First Release
    • Expose unsafe interfase of Array and UFunc API

Dependencies

~3.5MB
~76K SLoC