質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

1332閲覧

PyO3で実装したpyfunctionをRustから呼び出す

myame

総合スコア3

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2021/04/21 12:40

前提・実現したいこと

PyO3で実装したpyfunctionを、同じrustのプログラムから呼び出すことは不可能なのでしょうか?

該当のソースコード

rust

1#[pyfunction] 2fn one() -> f32 { 3 1. 4} 5 6fn main() { 7 let gil = Python::acquire_gil(); 8 let py = gil.python(); 9 // 以下のような処理をしたい 10 py.run("print(one())"); 11}

試したこと

バイナリクレートの場合、#[pyfunction]マクロで自動的に読み込まれることがなさそうなのですが、手動で読み込む方法も見当たらなかったので質問させて頂きます。

補足情報(FW/ツールのバージョンなど)

Rustや関連するライブラリは、いずれも最新の安定版です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

PyO3のGitHubリポジトリーに上がっていた質問(issue 354)を参考にしたところ、うまくできたようです。

やり方ですが、pyfunctionな関数をPythonモジュールに入れ、それをPythonインタープリタの組み込み(built-in)モジュールとして登録します。登録にはPython C FFIの PyImport_AppendInittab 関数 を使います。

なお、参考にしたissueは2年前のものなので、そのままではコンパイルエラーになってしまいます。私の方で少し変更しましたが、もっといい方法があるかもしれません。(今日はじめてPyO3を触りました)

rust

1// Cargo.toml 2// 3// [dependencies] 4// pyo3 = "0.13.2" 5 6use std::ffi::CString; 7use pyo3::prelude::*; 8 9#[pyfunction] 10fn one() -> f32 { 11 1. 12} 13 14// one関数をmy_moduleモジュールに登録する 15// #[pymodule]により、モジュールを初期化するunsafeな関数 16// PyInit_my_moduleが生成される 17#[pymodule] 18fn my_module(_py: Python, m: &PyModule) -> PyResult<()> { 19 m.add_function(pyo3::wrap_pyfunction!(one, m)?)?; 20 Ok(()) 21} 22 23// PyImport_AppendInittabはunsafeなモジュール初期化関数を 24// 受け付けないので、safeな関数でラップする 25extern "C" fn my_module_init() -> *mut pyo3::ffi::PyObject { 26 unsafe { PyInit_my_module() } 27} 28 29fn main() -> Result<(), Box<dyn std::error::Error>> { 30 // 31 // my_moduleをPythonインタープリタの組み込みモジュールとして登録する 32 // 33 let module_name = CString::new("my_module")?.into_raw(); 34 unsafe { 35 pyo3::ffi::PyImport_AppendInittab(module_name, Some(my_module_init)); 36 } 37 38 // 39 // Pythonインタープリタでmy_moduleからone関数をインポートし、実行する 40 // 41 let py_code = r#" 42from my_module import one 43print(one()) 44"#; 45 let gil = Python::acquire_gil(); 46 let py = gil.python(); 47 py.run(py_code, None, None)?; 48 Ok(()) 49}

環境

  • Rust 1.51.0
  • PyO3 0.13.2
  • Python 3.8.8
  • Linux x86_64 (NixOS)

投稿2021/04/23 10:16

編集2021/04/23 10:27
tatsuya6502

総合スコア2046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

myame

2021/04/25 01:15

ご回答下さりありがとうございます。 > やり方ですが、pyfunctionな関数をPythonモジュールに入れ、それをPythonインタープリタの組み込み(built-in)モジュールとして登録します。登録にはPython C FFIの PyImport_AppendInittab 関数 を使います。 グローバル関数として登録するのは、思っているよりもハードルが高いのですね。(Rustの学習を始めたばかりで、unsafeの概念も完全には理解できていないです...) とりあえずは`wrap_pyfunction!`で生成したpyfunctionを、`py.run`の引数 localに追加する手法で実装していこうと思います。 ありがとうございました????
tatsuya6502

2021/04/26 01:00

> とりあえずは`wrap_pyfunction!`で生成したpyfunctionを、`py.run`の引数 localに追加する手法で実装していこうと思います。 そういうやり方もできるんですね。勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問