Ruby support #1

Open
jaroslaw wants to merge 165 commits from ruby into main
2 changed files with 30 additions and 9 deletions
Showing only changes of commit 356e552ce7 - Show all commits

View file

@ -31,7 +31,7 @@ mlua = { version = "0.9.8", features = [
"vendored", "vendored",
"send", "send",
], optional = true } ], optional = true }
magnus = { version = "0.7.1", optional = true, features = ["embed"] } magnus = { version = "0.7.1", optional = true, features = ["embed", "rb-sys"] }
crossbeam-channel = "0.5.15" crossbeam-channel = "0.5.15"
rb-sys = "0.9.114" rb-sys = "0.9.114"

View file

@ -1,5 +1,8 @@
// TODO: maybe make all runtime engines not send and spawn threads for them like Ruby // TODO: maybe make all runtime engines not send and spawn threads for them like Ruby
// TODO: make sure ruby is statically linked // TODO: make sure ruby is statically linked
// TODO: add tests for every runtime for return value
// TODO: consider dropping magnus
// TODO: unwinding https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions
use std::{ use std::{
collections::HashMap, collections::HashMap,
ffi::{c_void, CString}, ffi::{c_void, CString},
@ -12,9 +15,9 @@ use bevy::{
ecs::{component::Component, resource::Resource, schedule::ScheduleLabel}, ecs::{component::Component, resource::Resource, schedule::ScheduleLabel},
reflect::TypePath, reflect::TypePath,
}; };
use magnus::Ruby; use magnus::{function, Ruby};
use magnus::{function, prelude::*}; use magnus::{prelude::*, rb_sys::FromRawValue};
use rb_sys::rb_define_global_function; use rb_sys::{rb_define_global_function, rb_scan_args, VALUE};
use serde::Deserialize; use serde::Deserialize;
use crate::{ use crate::{
@ -209,27 +212,45 @@ impl Runtime for RubyRuntime {
let mut callbacks = RUBY_CALLBACKS.lock().unwrap(); let mut callbacks = RUBY_CALLBACKS.lock().unwrap();
callbacks.insert(name.clone(), Box::new(f)); callbacks.insert(name.clone(), Box::new(f));
unsafe extern "C" fn callback(_rb_self: magnus::Value) -> magnus::Value { unsafe extern "C" fn callback(argc: i32, argv: *mut VALUE, r_self: VALUE) -> VALUE {
let fmt = CString::new("1").unwrap();
let x: VALUE = Default::default();
rb_scan_args(argc, argv, fmt.as_ptr(), &x);
let ruby = magnus::Ruby::get().unwrap(); let ruby = magnus::Ruby::get().unwrap();
let method_name: magnus::value::StaticSymbol = let method_name: magnus::value::StaticSymbol =
ruby.class_object().funcall("__method__", ()).unwrap(); ruby.class_object().funcall("__method__", ()).unwrap();
let method_name = method_name.to_string(); let method_name = method_name.to_string();
let callbacks = RUBY_CALLBACKS.lock().unwrap(); let callbacks = RUBY_CALLBACKS.lock().unwrap();
let f = callbacks.get(&method_name).unwrap(); let f = callbacks.get(&method_name).unwrap();
f((), vec![]).unwrap();
ruby.qnil().as_value() let args = magnus::RArray::from_value(magnus::Value::from_raw(*argv).into())
.unwrap()
.to_value_array::<1>()
.expect("failed to get args array");
for arg in args {
dbg!(arg);
}
// let args = args
// .parse(&self.engine)
// .into_iter()
// .map(|a| a.0)
// .collect::<Vec<Dynamic>>();
f((), vec![]).expect("failed to call callback");
todo!()
} }
self.ruby_thread self.ruby_thread
.as_ref() .as_ref()
.unwrap() .unwrap()
.execute(Box::new(move |ruby| { .execute(Box::new(move |_ruby| {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
unsafe { unsafe {
rb_define_global_function( rb_define_global_function(
name.as_ptr(), name.as_ptr(),
std::mem::transmute(callback as *mut c_void), std::mem::transmute(callback as *mut c_void),
1, -1,
); );
} }
RubyValue(()) RubyValue(())