Slide 1

Slide 1 text

Rustから Pythonを呼び出す @_sunnyone

Slide 2

Slide 2 text

Rust 1.0 リリース おめでとうございます!

Slide 3

Slide 3 text

なぜRustからPythonを呼び出したいか? ● Pythonを呼び出すDLL (unmanaged) を作りたい ● CやC++はもう避けたいが、LLは厳しそう... – Rustならできるんじゃね? とりあえずPython呼び出してみた

Slide 4

Slide 4 text

「rust-cpython」crate ● 便利なラッパーライブラリがすでに存在 – https://github.com/dgrunwald/rust-cpython ● rust-nightlyで使用可 $ cargo new hogehoge $ cd hogehoge $ vi Cargo.toml [dependencies.cpython] version = "*"

Slide 5

Slide 5 text

コード例 extern crate cpython; use cpython::{PythonObject, Python}; fn main() { let gil_guard = Python::acquire_gil(); let py = gil_guard.python(); let sys = py.import("sys").unwrap(); let version = sys.get("version").unwrap()                 .extract::().unwrap(); println!("Hello Python \"{}\"", version); }

Slide 6

Slide 6 text

実行例 $ cargo run Running `target/debug/rusttest` Hello Python "2.7.6 (default, Mar 22 2014, 23:03:14) [GCC 4.8.2]"

Slide 7

Slide 7 text

特徴的なところ extern crate cpython; use cpython::{PythonObject, Python}; fn main() { let gil_guard = Python::acquire_gil(); let py = gil_guard.python(); let sys = py.import("sys").unwrap(); let version = sys.get("version").unwrap()                 .extract::().unwrap(); println!("Hello Python \"{}\"", version); } GIL (Giant Interpreter Lock) 獲得にRAIIを活用 ↓ PyGILState_Ensure() と PyGILState_Release() 呼び出しが簡略化

Slide 8

Slide 8 text

acquire_gil実装部分 #[must_use] pub struct GILGuard { gstate: ffi::PyGILState_STATE } impl GILGuard { pub fn acquire() -> GILGuard { ::pythonrun::prepare_freethreaded_python(); let gstate = unsafe { ffi::PyGILState_Ensure() }; GILGuard { gstate: gstate } } } impl !Send for GILGuard {} impl Drop for GILGuard { fn drop(&mut self) { unsafe { ffi::PyGILState_Release(self.gstate) } } } pythonrun.rs (抜粋+コメント削除/順序他編集) Ensureしたstateを GILGuard構造体に保存 Drop traitで Release

Slide 9

Slide 9 text

罠 ● コンパイルできない src/objects/num.rs:81:23: 81:59 error: unresolved name `std::num::cast` src/objects/num.rs:81 match std::num::cast::(val) { src/objects/num.rs:61:1: 88:3 note: in expansion of int_fits_c_long! src/objects/num.rs:116:1: 116:22 note: expansion site src/objects/num.rs:81:23: 81:59 error: unresolved name `std::num::cast` src/objects/num.rs:81 match std::num::cast::(val) {

Slide 10

Slide 10 text

罠 ● src/objects/num.rsを見ると… // TODO: manual implementation for i64 on systems with 32-bit long // TODO: manual implementation for i64 on systems with 32-bit long (つд ) ⊂ ゴシゴシ (;゚д゚)

Slide 11

Slide 11 text

罠 ● Pythonの側はC-styleなサイズ – プラットフォームごとにi32などからの変換が必要 – http://docs.python.jp/2/library/stdtypes.html#int-float- long-complex ● 今回はLinux/x86だったのでひっかかった ● Linux(他)/x64, Windows/x86, x64はいけそう ● 一応isizeの変換コードを外せばコンパイルできる – https://github.com/sunnyone/rust- cpython/tree/feature/linux-32

Slide 12

Slide 12 text

ご清聴ありがとうございました