From cbde11d17b2f12ab5da2ffa5741b8cbb09667138 Mon Sep 17 00:00:00 2001 From: Jaroslaw Konik Date: Mon, 12 May 2025 12:08:04 +0200 Subject: [PATCH] callbacks global --- src/callback.rs | 6 +++--- src/lib.rs | 5 ++++- src/runtimes/ruby.rs | 34 ++++++++++++++++++++++++++++++---- tests/tests.rs | 12 ++++++------ 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/callback.rs b/src/callback.rs index 0174950..416fcd7 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -65,7 +65,7 @@ where fn into_callback_system(self, world: &mut World) -> CallbackSystem; } -impl IntoCallbackSystem for FN +impl IntoCallbackSystem for FN where FN: IntoSystem<(), Out, Marker>, Out: for<'a> IntoRuntimeValueWithEngine<'a, Out, R>, @@ -90,12 +90,12 @@ where macro_rules! impl_tuple { ($($idx:tt $t:tt),+) => { - impl IntoCallbackSystem, Out, Marker> + impl IntoCallbackSystem, Out, Marker> for FN where FN: IntoSystem, Out, Marker>, Out: for<'a> IntoRuntimeValueWithEngine<'a, Out, RN>, - $($t: 'static + for<'a> FromRuntimeValueWithEngine<'a, RN>,)+ + $($t: Send + 'static + for<'a> FromRuntimeValueWithEngine<'a, RN>,)+ { fn into_callback_system(self, world: &mut World) -> CallbackSystem { let mut inner_system = IntoSystem::into_system(self); diff --git a/src/lib.rs b/src/lib.rs index bc72d3e..a3d3364 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -303,7 +303,10 @@ pub trait Runtime: Resource + Default { /// Provides mutable reference to raw scripting engine instance. /// Can be used to directly interact with an interpreter to use interfaces /// that bevy_scriptum does not provided adapters for. - fn with_engine_mut(&mut self, f: impl FnOnce(&mut Self::RawEngine) -> T) -> T; + fn with_engine_mut( + &mut self, + f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static, + ) -> T; /// Provides immutable reference to raw scripting engine instance. /// Can be used to directly interact with an interpreter to use interfaces diff --git a/src/runtimes/ruby.rs b/src/runtimes/ruby.rs index c9f4568..bc6d6e2 100644 --- a/src/runtimes/ruby.rs +++ b/src/runtimes/ruby.rs @@ -1,6 +1,6 @@ // TODO: make sure ruby is statically linked use std::{ - sync::LazyLock, + sync::{LazyLock, Mutex}, thread::{self, JoinHandle}, }; @@ -49,6 +49,7 @@ struct RubyThread { handle: Option>, } +// TODO: Can we put references to those in runtime struct? static RUBY_THREAD: LazyLock = LazyLock::new(|| RubyThread::spawn()); impl RubyThread { @@ -112,8 +113,11 @@ impl Runtime for RubyRuntime { type RawEngine = magnus::Ruby; - fn with_engine_mut(&mut self, f: impl FnOnce(&mut Self::RawEngine) -> T) -> T { - f(&mut magnus::Ruby::get().unwrap()) + fn with_engine_mut( + &mut self, + f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static, + ) -> T { + RUBY_THREAD.execute_in(Box::new(move |mut ruby| f(&mut ruby))) } fn with_engine( @@ -150,12 +154,34 @@ impl Runtime for RubyRuntime { + Sync + 'static, ) -> Result<(), crate::ScriptingError> { + static RUBY_CALLBACKS: LazyLock< + Mutex< + Vec< + Box< + dyn Fn( + (), + Vec, + ) -> Result< + crate::promise::Promise<(), RubyValue>, + crate::ScriptingError, + > + Send + + Sync + + 'static, + >, + >, + >, + > = LazyLock::new(|| Mutex::new(Vec::new())); + let mut callbacks = RUBY_CALLBACKS.lock().unwrap(); + callbacks.push(Box::new(f)); + fn callback() -> magnus::Value { let ruby = magnus::Ruby::get().unwrap(); let method_name: magnus::value::StaticSymbol = ruby.class_object().funcall("__method__", ()).unwrap(); let method_name = method_name.to_string(); - dbg!(method_name); + let mut callbacks = RUBY_CALLBACKS.lock().unwrap(); + let f = callbacks.pop().unwrap(); + f((), vec![]); ruby.qnil().as_value() } diff --git a/tests/tests.rs b/tests/tests.rs index 7e936fb..818d035 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -493,13 +493,13 @@ mod ruby_tests { type ScriptData = RubyScriptData; fn assert_state_key_value_i64(world: &World, _entity_id: Entity, key: &str, value: i64) { - // let state: magnus::value::Value = Ruby::get() - // .unwrap() - // .class_object() - // .const_get("STATE") - // .unwrap(); - // let res: i64 = state.funcall_public("[]", (key.to_string(),)).unwrap(); + // let runtime = world.get_resource::().unwrap(); + // let key = key.to_string(); + // runtime.with_engine(move |engine| { + // let state: magnus::value::Value = engine.class_object().const_get("STATE").unwrap(); + // let res: i64 = state.funcall_public("[]", (key,)).unwrap(); // assert_eq!(res, value) + // }) } fn assert_state_key_value_i32(world: &World, _entity_id: Entity, key: &str, value: i32) {