Skip to content

Instantly share code, notes, and snippets.

@ssokolow
Last active April 14, 2021 21:43
Show Gist options
  • Save ssokolow/34ce62a0d98054810c488a7f0d3fd4e0 to your computer and use it in GitHub Desktop.
Save ssokolow/34ce62a0d98054810c488a7f0d3fd4e0 to your computer and use it in GitHub Desktop.
Simple example of getting the rust-cpython and setuptools-rust examples working together
# hello_rust/__init__.py just needs to exist and not be invalid Python
# hello_rust/__main__.py
from . import _helloworld
def main():
print("Calculated with Rust: " + _helloworld.sum_as_string(1, 2))
# This allows main() to be called both via `python -m`
# and via setuptools entry points.
if __name__ == '__main__':
main()
[package]
name = "unimportant_if_subsumed_by_setuptools"
version = "0.1.0"
authors = ["Your Name Here <[email protected]>"]
[lib]
name = "unimportant_if_subsumed_by_setuptools"
crate-type = ["cdylib"]
[dependencies.cpython]
version = "0.1"
default-features = false
features = ["python27-sys", "extension-module-2-7"]
# NOTE: If using Python 3, replace `default-features` and `features` lines with this:
# features = ["extension-module"]
# Clear out all built files
clean:
cargo clean
rm hello_rust/*.so hello_rust/*.pyc || true
# vim: set ft=make textwidth=100 colorcolumn=101 noexpandtab sw=8 sts=8 ts=8 :
// src/lib.rs
#[macro_use] extern crate cpython;
use cpython::{PyResult, Python};
// add bindings to the generated python module
// N.B: names: "_helloworld" must be the name of the `.so` or `.pyd` file
py_module_initializer!(_helloworld, init_helloworld, PyInit__helloworld, |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.
// Note that the py_fn!() macro automatically converts the arguments from
// Python objects to Rust values; and the Rust return value back into a Python object.
fn sum_as_string_py(_: Python, a:i64, b:i64) -> PyResult<String> {
let out = sum_as_string(a, b);
Ok(out)
}
#!/bin/sh
# Playing things safe and allowing this to be used for testing changes to setup.py
deactivate
rm -rf venv
# The actual meat of the script
virtualenv venv &&
. ./venv/bin/activate &&
python setup.py develop
python -m hello_rust
from setuptools import setup
# Workaround from https://github.com/PyO3/setuptools-rust/issues/2
try:
from setuptools_rust import Binding, RustExtension
except ImportError:
import os, subprocess, sys
try:
subprocess.check_call([sys.executable, '-m', 'pip',
'install', 'setuptools-rust'])
os.execvp(sys.executable, [sys.executable] + sys.argv)
except subprocess.CalledProcessError as err:
print("Please install setuptools-rust package")
raise SystemExit(err.errno)
setup(name='hello-rust',
version='1.0',
rust_extensions=[RustExtension('hello_rust._helloworld',
'Cargo.toml',
binding=Binding.RustCPython)],
packages=['hello_rust'],
# rust extensions are not zip safe, just like C-extensions.
zip_safe=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment