youtube:python-mixing-009
PyO3でLÖVEもどきを作る (2)
作成日: 2023-08-14 (月)
プロジェクト pyove
Cargo.toml
[package]
name = "pyove"
version = "0.1.0"
edition = "2021"
[dependencies.pyo3]
version = "0.19.2"
features = ["auto-initialize", "macros"]
src/main.rs
use pyo3::prelude::*;
use std::{env, path::Path, process::exit};
pub mod graphics;
#[pyfunction]
fn load() {
println!("default load");
}
#[pyfunction]
fn draw() {
println!("default draw");
}
#[pyfunction]
fn update(dt: f32) {
println!("default update {}", dt);
}
#[pymodule]
fn pyove(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(load, m)?)?;
m.add_function(wrap_pyfunction!(draw, m)?)?;
m.add_function(wrap_pyfunction!(update, m)?)?;
graphics::register_graphics_module(py, m)?;
Ok(())
}
fn main() -> PyResult<()> {
//
// コマンドライン引数のパース
//
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
// コマンドライン引数がただ1つだけ与えられていなければ終了する
eprintln!("Usage: {} GAMEDIR", args[0]);
exit(1);
}
let gamedir = Path::new(&args[1]);
let main_file = gamedir.join("main.py");
if !main_file.exists() {
// main.pyが存在しなければ終了する
eprintln!("Error: {} not exists.", main_file.to_str().unwrap());
exit(2);
}
// main.pyの内容を読み込む
let main_code = std::fs::read_to_string(main_file)?;
//
// activate Python interpreter
//
// pyoveをモジュールとして登録
pyo3::append_to_inittab!(pyove);
Python::with_gil(|py| {
// ゲームディレクトリをインポートパスに追加する
let sys_path_code = format!(
"import sys; sys.path.append('{}')",
gamedir.to_str().unwrap()
);
py.run(&sys_path_code, None, None)?;
// pyoveモジュールにアクセスしたいので、ここでインポートする
let pyove = PyModule::import(py, "pyove")?;
// main.pyを実行
py.run(&main_code, None, None)?;
// main.pyでこの3つの関数は置き換え可能
let load_fn = pyove.getattr("load")?;
let update_fn = pyove.getattr("update")?;
let draw_fn = pyove.getattr("draw")?;
// 試しにloadとupdateとdrawを実行してみる
load_fn.call0()?;
update_fn.call1((123,))?;
draw_fn.call0()?;
Ok(())
})
}
src/graphics.rs
//
// このプロジェクトではset_colorとrectangle関数のみを提供する
//
use pyo3::prelude::*;
#[pyfunction]
#[pyo3(name = "setColor")]
fn set_color(r: f32, g: f32, b: f32) {
// 仮の処理
println!("setColor {} {} {}", r, g, b);
}
#[pyfunction]
fn rectangle(mode: &str, x: i32, y: i32, w: i32, h: i32) {
// 仮の処理
println!("rectangle {} {} {} {} {}", mode, x, y, w, h)
}
pub fn register_graphics_module(py: Python<'_>, parent_module: &PyModule) -> PyResult<()> {
// see: https://pyo3.rs/v0.19.2/module#python-submodules
// サブモジュールとしてgraphicsを登録する
// graphicsに、setColorとrectangleを登録する
let m = PyModule::new(py, "graphics")?;
m.add_function(wrap_pyfunction!(set_color, m)?)?;
m.add_function(wrap_pyfunction!(rectangle, m)?)?;
parent_module.add_submodule(m)?;
Ok(())
}
example/main.py
import pyove
#import foo # test import availability
# Python requires global scoped variable definitions
x, y, w, h = 0, 0, 0, 0
def load():
global x, y, w, h
x, y, w, h = 20, 20, 60, 20
def update(dt):
global w, h
w += 1
h += 1
def draw():
pyove.graphics.setColor(0, 0.4, 0.4)
pyove.graphics.rectangle("fill", x, y, w, h)
# overwrite default module functions
pyove.load = load
pyove.draw = draw
pyove.update = update
参考
オリジナルの動作は、こちらを参考にしてください。
youtube/python-mixing-009.txt · 最終更新: 2024/02/28 18:26 by freemikan