rlgym_learn_backend/common/
misc.rs1use std::mem::align_of;
2
3use pyo3::{
4 intern,
5 sync::GILOnceCell,
6 types::{PyAnyMethods, PyDict},
7 Bound, IntoPyObject, PyAny, PyErr, PyObject, PyResult, Python,
8};
9use which;
10
11pub fn py_hash(v: &Bound<'_, PyAny>) -> PyResult<i64> {
12 v.call_method0(intern!(v.py(), "__hash__"))?
13 .extract::<i64>()
14}
15
16static INTERNED_CAT: GILOnceCell<PyObject> = GILOnceCell::new();
17static INTERNED_EMPTY: GILOnceCell<PyObject> = GILOnceCell::new();
18
19pub fn get_bytes_to_alignment<T>(addr: usize) -> usize {
20 let alignment = align_of::<T>();
21 let aligned_addr = addr.wrapping_add(alignment - 1) & 0usize.wrapping_sub(alignment);
22 aligned_addr.wrapping_sub(addr)
23}
24
25#[allow(dead_code)]
26pub fn initialize_python() -> pyo3::PyResult<()> {
27 let python_exe = which::which("python").unwrap();
31 let python_home = python_exe.parent().unwrap();
32 let mut python_home = python_home
37 .to_str()
38 .unwrap()
39 .encode_utf16()
40 .collect::<Vec<u16>>();
41 python_home.push(0);
42 unsafe {
43 pyo3::ffi::Py_SetPythonHome(python_home.as_ptr());
44 }
45 pyo3::prepare_freethreaded_python();
48 Python::with_gil::<_, PyResult<_>>(|py| {
50 Ok(py
51 .import("sys")?
52 .getattr("path")?
53 .call_method1("insert", (0, std::env::current_dir()?.to_str().unwrap()))?
54 .unbind())
55 })?;
56 Ok(())
57}
58
59pub fn clone_list<'py>(py: Python<'py>, list: &Vec<PyObject>) -> Vec<PyObject> {
60 list.iter().map(|obj| obj.clone_ref(py)).collect()
61}
62
63pub fn tensor_slice_1d<'py>(
64 py: Python<'py>,
65 tensor: &Bound<'py, PyAny>,
66 start: usize,
67 stop: usize,
68) -> PyResult<Bound<'py, PyAny>> {
69 Ok(tensor.call_method1(intern!(py, "narrow"), (0, start, stop - start))?)
70}
71
72pub fn torch_cat<'py>(py: Python<'py>, obj: &[&PyObject]) -> PyResult<Bound<'py, PyAny>> {
73 Ok(INTERNED_CAT
74 .get_or_try_init::<_, PyErr>(py, || Ok(py.import("torch")?.getattr("cat")?.unbind()))?
75 .bind(py)
76 .call1((obj,))?)
77}
78
79pub fn torch_empty<'py>(
80 shape: &Bound<'py, PyAny>,
81 dtype: &Bound<'py, PyAny>,
82) -> PyResult<Bound<'py, PyAny>> {
83 let py = shape.py();
84 Ok(INTERNED_EMPTY
85 .get_or_try_init::<_, PyErr>(py, || Ok(py.import("torch")?.getattr("empty")?.unbind()))?
86 .bind(py)
87 .call(
88 (shape,),
89 Some(&PyDict::from_sequence(
90 &vec![(intern!(py, "dtype"), dtype)].into_pyobject(py)?,
91 )?),
92 )?)
93}