PyO3を使ってPythonからRustの関数を呼び出してみる
今回は、表題の通り、PyO3を使ってPythonからRustの関数を呼び出してみたのでその備忘録です。
初めは難しいのかなぁと思いましたが、やってみると結構簡単に出来ました(まだ簡単なところしかやってないからかもしれませんが、笑)
まずはコマンドプロンプト等からcargo new rs2py --lib
と打ち、今回のを試してみる用のライブラリクレート「rs2py」を作ります。その後、作成された「rs2py」内のtomlファイルを以下のように記述します。
[package] ...(色々書かれている) [lib] name = "rs2py" crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.15.1", features = [ "extension-module", ] }
tomlファイルでは、crate-type = ["cdylib"]
とし、で共有ライブラリを作るようにします。
後はpyo3の依存を追加します。
ちなみに、以前はpyo3はnightly-rustでしか使用できなかったみたいですが、今は(pyo3のバージョンが0.11から)stableなRustで扱えるようになったらしいです。
さて、これでtomlファイルの準備は完了しましたので、次はlib.rsを書いていきます。 今回は初めての挑戦ということで、呼ばれたら「Hello, world!」と出力されるような簡単な関数を記述していきます。
use pyo3::prelude::*; use pyo3::wrap_pyfunction; #[pymodule] fn rs2py(_py: Python, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pyfunction!(hello))?; Ok(()) } #[pyfunction] fn hello() -> PyResult<()> { println!("Hello, world!"); Ok(()) }
このコードの中で大切な点としては
- Python から呼び出したい関数には #[pyfunction]を書く
- Pythonのモジュールとしてみせたいものには#[pymodule] をつけた関数として定義する
- 戻り値は PyResult
にする必要がある(戻り値のない場合は PyResult<()>)
みたいです。この辺りは私もまだ知識不足で正しく理解できていませんが。。。
さて、lib.rsファイルも書けたらcargo build --release
でビルドをしましょう。
ビルドをすると、target\releaseフォルダに色々なファイルが出来ますが、その中の「rs2py.dll」が、私達が欲しいものです。これを「rs2.py.pyd」と拡張子を変更してください。
これでライブラリの準備ができましたので、pythonで呼び出せることを確認しましょう。同じフォルダに適当な名前でPythonファイルを作成し、中に下記のようなコードを書きましょう。
import rs2py
rs2py.hello()
書けたらそのPythonファイルを実行してみてください。「Hello, world!」と表示されたら成功です。
今回はここまで、これをきっかけにして今後RustとPythonで色々連携できるようにしたいと思います。