From d0746fa5dbf8a410dbecc57ec1bff135f8395cfb Mon Sep 17 00:00:00 2001 From: Jaroslaw Konik Date: Mon, 19 May 2025 07:00:00 +0200 Subject: [PATCH] rb static link --- .cargo/config.toml | 7 +++++++ Cargo.toml | 3 ++- assets/tests/lua/pass_vec3_to_script.lua | 7 +++---- assets/tests/rhai/pass_vec3_to_script.rhai | 5 +++-- assets/tests/ruby/pass_vec3_to_script.rb | 2 +- src/runtimes/ruby.rs | 21 +++++++++++++++------ 6 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..e44bca7 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +# Without this flag, when linking static libruby, the linker removes symbols +# (such as `_rb_ext_ractor_safe`) which it thinks are dead code... but they are +# not, and they need to be included for the `embed` feature to work with static +# Ruby. +# rustflags = ["-C", "link-args=-lz", "-C", "link-dead-code=on"] +rustflags = ["-C", "link-args=-lz"] diff --git a/Cargo.toml b/Cargo.toml index 0ab04f3..759fcf2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ keywords = ["bevy", "rhai", "scripting", "game", "gamedev"] [features] lua = ["dep:mlua", "mlua/luajit"] rhai = ["dep:rhai"] -ruby = ["dep:magnus"] +ruby = ["dep:magnus", "dep:rb-sys"] [dependencies] bevy = { default-features = false, version = "0.16", features = ["bevy_asset", "bevy_log"] } @@ -32,6 +32,7 @@ mlua = { version = "0.9.8", features = [ "send", ], optional = true } magnus = { version = "0.7.1", optional = true, features = ["embed"] } +rb-sys = { version = "*", default-features = false, features = ["link-ruby", "ruby-static"], optional = true } crossbeam-channel = "0.5.15" [[example]] diff --git a/assets/tests/lua/pass_vec3_to_script.lua b/assets/tests/lua/pass_vec3_to_script.lua index 4a9d395..0b50c5c 100644 --- a/assets/tests/lua/pass_vec3_to_script.lua +++ b/assets/tests/lua/pass_vec3_to_script.lua @@ -1,7 +1,6 @@ function test_func(vec3) - -- raise unless vec3.is_a?(Vec3) # TODO: BevyScriptum::Vec3 and add example how to include it globally like Sinatra does - -- raise unless vec3.x == 1.5 - -- raise unless vec3.y == 2.5 - -- raise unless vec3.z == -3.5 + assert(vec3.x == 1.5) + assert(vec3.y == 2.5) + assert(vec3.z == -3.5) mark_success() end diff --git a/assets/tests/rhai/pass_vec3_to_script.rhai b/assets/tests/rhai/pass_vec3_to_script.rhai index e0550d0..4d04eb1 100644 --- a/assets/tests/rhai/pass_vec3_to_script.rhai +++ b/assets/tests/rhai/pass_vec3_to_script.rhai @@ -1,4 +1,5 @@ fn test_func(vec3) { - // TODO: asser vec3 correctness - mark_success() + if type_of(vec3) != "tests::rhai_tests::BevyVec3" { throw() } + // TODO: assert x,y,z + mark_success(); } diff --git a/assets/tests/ruby/pass_vec3_to_script.rb b/assets/tests/ruby/pass_vec3_to_script.rb index 4d27eac..477ba1a 100644 --- a/assets/tests/ruby/pass_vec3_to_script.rb +++ b/assets/tests/ruby/pass_vec3_to_script.rb @@ -1,5 +1,5 @@ def test_func(vec3) - raise unless vec3.is_a?(Bevy::Vec3) # TODO: BevyScriptum::Vec3 and add example how to include it globally like Sinatra does + raise unless vec3.is_a?(Bevy::Vec3) raise unless vec3.x == 1.5 raise unless vec3.y == 2.5 raise unless vec3.z == -3.5 diff --git a/src/runtimes/ruby.rs b/src/runtimes/ruby.rs index 2c6e535..3d557a3 100644 --- a/src/runtimes/ruby.rs +++ b/src/runtimes/ruby.rs @@ -12,10 +12,13 @@ use bevy::{ tasks::futures_lite::io, }; use magnus::{ - block::Proc, data_type_builder, function, value::Lazy, DataType, DataTypeFunctions, IntoValue, - Object, RClass, RModule, Ruby, TryConvert, TypedData, + block::Proc, + data_type_builder, function, + value::{Lazy, ReprValue}, + DataType, DataTypeFunctions, IntoValue, Object, RClass, RModule, Ruby, TryConvert, TypedData, }; use magnus::{method, prelude::*}; +use rb_sys::{ruby_finalize, ruby_init_stack, VALUE}; use serde::Deserialize; use crate::{ @@ -66,11 +69,18 @@ impl RubyThread { let (sender, receiver) = crossbeam_channel::unbounded::>(); let handle = thread::spawn(move || { - let _cleanup = unsafe { magnus::embed::init() }; + unsafe { + let mut variable_in_this_stack_frame: VALUE = 0; + ruby_init_stack(&mut variable_in_this_stack_frame as *mut VALUE as *mut _); + rb_sys::ruby_init() + }; while let Ok(f) = receiver.recv() { let ruby = Ruby::get().expect("Failed to get a handle to Ruby API"); f(ruby); } + unsafe { + ruby_finalize(); + } }); RubyThread { @@ -364,9 +374,9 @@ impl Runtime for RubyRuntime { 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(); + let method_name = method_name.name().unwrap(); let callbacks = RUBY_CALLBACKS.lock().unwrap(); - let f = callbacks.get(&method_name).unwrap(); + let f = callbacks.get(method_name).unwrap(); let result = f( (), args.iter() @@ -422,7 +432,6 @@ impl Runtime for RubyRuntime { })) } - // TODO: add test fn call_fn_from_value( &self, value: &Self::Value,