この記事は Rust Advent Calendar 2016 12日目の記事です。
今回はRustでPythonライブラリを書けるライブラリの rust-cpython を紹介します。

rust-cpython

dgrunwald/rust-cpython -Github-

rust-cpythonはRustからPythonを実行したり, Rustで書いた処理をCythonの様にpythonから実行できるライブラリを作成することができます。
以下の各バージョンがサポートされています。
  • Python 2.7, 3.3-3.5
  • Rust 1.7以降

pythonからRustで実装した処理を実行する

Cargo.tomlに以下の内容を記載します。
[lib]
name = "rustpy"  # ここはお好きな名前で
# dylib 生成するオプション指定
crate-type = ["dylib"]

[dependencies]
# cpythonを追加
cpython = { git = "https://github.com/dgrunwald/rust-cpython.git" }
libとして実行する場合は src/lib.rs で作成し, main関数は必要ありません。
#[macro_use] extern crate cpython;

use cpython::{PyResult, Python};

// add bindings to the generated python module
py_module_initializer!(librustpy, initlibrustpy, PyInit_librustpy, |py, m| {
    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()
}

// 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)
}
上記のファイルを作成し, buildを実行する。
$ cargo build
...
   Compiling thread_local v0.2.7
   Compiling regex v0.1.80
   Compiling python3-sys v0.1.2 (https://github.com/dgrunwald/rust-cpython.git#278c1aec)
error: failed to run custom build command for `python3-sys v0.1.2 (https://github.com/dgrunwald/rust-cpython.git#278c1aec)`
process didn't exit successfully: `/home/vagrant/rustpy/target/debug/build/python3-sys-64a280ab2538552e/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "python script failed with stderr:\n\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nImportError: No module named sysconfig\n"', ../src/libcore/result.rs:799
note: Run with `RUST_BACKTRACE=1` for a backtrace.
python3関連でエラーが発生してしまいました...。
実行環境はpyenvでpython2.7でした。
pyenvで2系, 3系の両方を設定しておきます。
$ pyenv global 2.7.12 3.5.1
$ cargo build
...
   Compiling python3-sys v0.1.2 (https://github.com/dgrunwald/rust-cpython.git#278c1aec)
   Compiling rustpy v0.1.0 (file:///Users/hoge/dev/rust/rustpy)
    Finished debug [unoptimized + debuginfo] target(s) in 21.45 secs
./target/debug/librustpy.so が作成されているので, python インタープリタを実行。
$ python
Python 2.7.11 (default, Mar 22 2016, 23:19:30)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import librustpy
Fatal Python error: take_gil: NULL tstate
[1]    44542 segmentation fault  python
...まさかのセグメンテーションフォールトが起こってしまいました。
もう少し調査にして動く状態を後程追記します。

おわりに

公式ドキュメントや他の方の実行では動いているようです。
ですので本当はpythonからRustで実装した処理をCythonに近い実行速度で実行できるようなので, python好きなRustの人でCython書くのはちょっと...って人にはオススメかもしれません。
以上、Rust Advent Calendar 2016 12日目の記事でした。

Related Posts