init python lib generation with pyo3

This commit is contained in:
Henri Bourcereau 2025-02-08 13:28:42 +01:00
parent 59c80c66e4
commit 883d799edb
8 changed files with 201 additions and 6 deletions

103
Cargo.lock generated
View file

@ -396,6 +396,12 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "indoc"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
[[package]] [[package]]
name = "inout" name = "inout"
version = "0.1.3" version = "0.1.3"
@ -490,6 +496,15 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "merge" name = "merge"
version = "0.1.0" version = "0.1.0"
@ -550,6 +565,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a74f2cda724d43a0a63140af89836d4e7db6138ef67c9f96d3a0f0150d05000" checksum = "3a74f2cda724d43a0a63140af89836d4e7db6138ef67c9f96d3a0f0150d05000"
[[package]]
name = "once_cell"
version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"
version = "0.3.0" version = "0.3.0"
@ -602,6 +623,12 @@ dependencies = [
"universal-hash", "universal-hash",
] ]
[[package]]
name = "portable-atomic"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@ -651,6 +678,69 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "pyo3"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57fe09249128b3173d092de9523eaa75136bf7ba85e0d69eca241c7939c933cc"
dependencies = [
"cfg-if",
"indoc",
"libc",
"memoffset",
"once_cell",
"portable-atomic",
"pyo3-build-config",
"pyo3-ffi",
"pyo3-macros",
"unindent",
]
[[package]]
name = "pyo3-build-config"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd3927b5a78757a0d71aa9dff669f903b1eb64b54142a9bd9f757f8fde65fd7"
dependencies = [
"once_cell",
"target-lexicon",
]
[[package]]
name = "pyo3-ffi"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dab6bb2102bd8f991e7749f130a70d05dd557613e39ed2deeee8e9ca0c4d548d"
dependencies = [
"libc",
"pyo3-build-config",
]
[[package]]
name = "pyo3-macros"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91871864b353fd5ffcb3f91f2f703a22a9797c91b9ab497b1acac7b07ae509c7"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
"quote",
"syn 2.0.79",
]
[[package]]
name = "pyo3-macros-backend"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43abc3b80bc20f3facd86cd3c60beed58c3e2aa26213f3cda368de39c60a27e4"
dependencies = [
"heck",
"proc-macro2",
"pyo3-build-config",
"quote",
"syn 2.0.79",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.37"
@ -871,6 +961,7 @@ dependencies = [
"base64", "base64",
"log", "log",
"merge", "merge",
"pyo3",
"rand", "rand",
"serde", "serde",
"transpose", "transpose",
@ -932,6 +1023,12 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.3.0" version = "1.3.0"
@ -998,6 +1095,12 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unindent"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
[[package]] [[package]]
name = "universal-hash" name = "universal-hash"
version = "0.5.1" version = "0.5.1"

View file

@ -1,14 +1,20 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
# https://devenv.sh/basics/
# env.GREET = "devenv";
packages = [ packages = [
# dev tools # dev tools
pkgs.samply # code profiler pkgs.samply # code profiler
# generate python classes from rust code (for AI training)
pkgs.maturin
# required to manually install generated python module in local venv
pkgs.python312Packages.pip
# required by python numpy (for AI training)
pkgs.libz
# for bevy # for bevy
pkgs.alsaLib pkgs.alsaLib
pkgs.udev pkgs.udev
@ -38,14 +44,26 @@
]; ];
# enterShell = '' enterShell = ''
# hello PYTHONPATH=$PYTHONPATH:$PWD/.devenv/state/venv/lib/python3.12/site-packages
# git --version '';
# '';
# https://devenv.sh/languages/ # https://devenv.sh/languages/
languages.rust.enable = true; languages.rust.enable = true;
# for AI training
languages.python = {
enable = true;
uv.enable = true;
venv.enable = true;
venv.requirements = "
gym
numpy
stable-baselines3
";
};
# https://devenv.sh/scripts/ # https://devenv.sh/scripts/
# scripts.hello.exec = "echo hello from $GREET"; # scripts.hello.exec = "echo hello from $GREET";

View file

@ -14,3 +14,6 @@ profile:
echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid echo '1' | sudo tee /proc/sys/kernel/perf_event_paranoid
cargo build --profile profiling cargo build --profile profiling
samply record ./target/profiling/client_cli --bot dummy,dummy samply record ./target/profiling/client_cli --bot dummy,dummy
pythonlib:
maturin build -m store/Cargo.toml --release
pip install --no-deps --force-reinstall --prefix .devenv/state/venv target/wheels/*.whl

View file

@ -5,11 +5,18 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "trictrac"
# "cdylib" is necessary to produce a shared library for Python to import from.
crate-type = ["cdylib"]
[dependencies] [dependencies]
base64 = "0.21.7" base64 = "0.21.7"
# provides macros for creating log messages to be used by a logger (for example env_logger) # provides macros for creating log messages to be used by a logger (for example env_logger)
log = "0.4.20" log = "0.4.20"
merge = "0.1.0" merge = "0.1.0"
# generate python lib to be used in AI training
pyo3 = { version = "0.23", features = ["extension-module", "abi3-py38"] }
rand = "0.8.5" rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
transpose = "0.2.2" transpose = "0.2.2"

10
store/pyproject.toml Normal file
View file

@ -0,0 +1,10 @@
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"
[tool.maturin]
# "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so)
features = ["pyo3/extension-module"]
# python-source = "python"
# module-name = "trictrac.game"

9
store/python/test.py Normal file
View file

@ -0,0 +1,9 @@
import trictrac
game = trictrac.TricTrac()
print(game.get_state()) # "Initial state"
moves = game.get_available_moves()
print(moves) # [(0, 5), (3, 8)]
game.play_move(0, 5)

42
store/src/engine.rs Normal file
View file

@ -0,0 +1,42 @@
//! # Expose trictrac game state and rules in a python module
use pyo3::prelude::*;
use pyo3::types::PyTuple;
#[pyclass]
struct TricTrac {
state: String, // Remplace par ta structure d'état du jeu
}
#[pymethods]
impl TricTrac {
#[new]
fn new() -> Self {
TricTrac {
state: "Initial state".to_string(),
}
}
fn get_state(&self) -> String {
self.state.clone()
}
fn get_available_moves(&self) -> Vec<(i32, i32)> {
vec![(0, 5), (3, 8)] // Remplace par ta logique de génération de coups
}
fn play_move(&mut self, from_pos: i32, to_pos: i32) -> bool {
// Ajoute la logique du jeu ici
println!("Move... from {} to {}", from_pos, to_pos);
true
}
}
/// A Python module implemented in Rust. The name of this function must match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
#[pymodule]
fn trictrac(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<TricTrac>()?;
Ok(())
}

View file

@ -16,3 +16,6 @@ pub use board::CheckerMove;
mod dice; mod dice;
pub use dice::{Dice, DiceRoller}; pub use dice::{Dice, DiceRoller};
// python interface "trictrac_engine" (for AI training..)
mod engine;