Rust bindings for the Python interpreter
Go to file
Daniel Grunwald 62a083e38f PyTuple: Add back iter() method (fixes build); require py: Python for as_slice().
This is a compromise solution: we require the GIL to be held when acquiring
the slice, but not later when using the slice.

We could bind the lifetime of the returned slice to the Python-token lifetime
to prevent accessing the slice when the GIL is not held, but that causes
problems with the FromPyObject impl.

Alternatively we could not require the GIL at all when accessing the PyTuple
(and thus keep the ops::Index and IntoIterator implementations), but that
relies on too many CPython implementation details for my taste.
2016-12-17 16:40:17 +01:00
examples Fix #10: Windows support. 2016-12-17 15:46:52 +01:00
extensions
python3-sys Fix #10: Windows support. 2016-12-17 15:46:52 +01:00
python27-sys Fix #10: Windows support. 2016-12-17 15:46:52 +01:00
src PyTuple: Add back iter() method (fixes build); require py: Python for as_slice(). 2016-12-17 16:40:17 +01:00
tests
.gitignore
.travis.yml Fix #10: Windows support. 2016-12-17 15:46:52 +01:00
Cargo.toml
LICENSE
Makefile
README.md Fix #10: Windows support. 2016-12-17 15:46:52 +01:00
appveyor.yml Fix #10: Windows support. 2016-12-17 15:46:52 +01:00
build.rs

README.md

rust-cpython Build Status

Rust bindings for the python interpreter.


Copyright (c) 2015-2016 Daniel Grunwald. Rust-cpython is licensed under the MIT license. Python is licensed under the Python License.

Supported Python versions:

  • Python 2.7
  • Python 3.3
  • Python 3.4
  • Python 3.5

Supported Rust version:

  • Rust 1.13.0 or later
  • On Windows, we require rustc 1.15.0-nightly

Usage

To use cpython, add this to your Cargo.toml:

[dependencies]
cpython = { git = "https://github.com/dgrunwald/rust-cpython.git" }

Example program displaying the value of sys.version:

extern crate cpython;

use cpython::{Python, PyDict, PyResult};

fn main() {
    let gil = Python::acquire_gil();
    hello(gil.python()).unwrap();
}

fn hello(py: Python) -> PyResult<()> {
    let sys = py.import("sys")?;
    let version: String = sys.get(py, "version")?.extract(py)?;

    let locals = PyDict::new(py);
    locals.set_item(py, "os", py.import("os")?)?;
    let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract(py)?;

    println!("Hello {}, I'm Python {}", user, version);
    Ok(())
}

Example library with python bindings:

The following two files will build with cargo build, and will generate a python-compatible library. (On macOS, you will need to rename the output from *.dynlib to *.so)

Cargo.toml:

[lib]
name = "rust2py"
crate-type = ["dylib"]

[dependencies]
cpython = { git = "https://github.com/dgrunwald/rust-cpython.git" }

src/lib.rs

#[macro_use] extern crate cpython;

use cpython::{PyResult, Python};

// add bindings to the generated python module
// N.B: names: "rust2py" must be the lib name in Cargo.toml
py_module_initializer!(librust2py, initlibrust2py, PyInit_librust2py, |py, m| {
    try!(m.add(py, "__doc__", "This module is implemented in Rust."));
    try!(m.add(py, "sum_as_string", py_fn!(py, sum_as_string_py(a: i64, b:i64))));
    Ok(())
});

// logic implemented as a normal rust function
fn sum_as_string(a:i64, b:i64) -> String {
    format!("{}", a + b).to_string()
}

// rust-cpython aware function. All of our python interface could be
// declared in a separate module. 
fn sum_as_string_py(_: Python, a:i64, b:i64) -> PyResult<String> {
    let out = sum_as_string(a, b);
    Ok(out)
}