public R_VAL ExecuteSet(RubyState state, object obj, CallbackArguments args) { var arg = args.RawGet(0, false); PropertyInfo.SetValue(obj, RubyState.ValueToObjectOfType(state, arg, DataTypePtr, PropertyInfo.PropertyType, PropertyInfo.PropertyType, false), null); return(R_VAL.NIL); }
/// <summary> /// Builds the return value of a call /// </summary> /// <param name="outParams">The out parameters indices, or null. See <see cref="BuildArgumentList" />.</param> /// <param name="pars">The parameters passed to the function.</param> /// <param name="retv">The return value from the function. Use DynValue.Void if the function returned no value.</param> /// <returns>A DynValue to be returned to scripts</returns> protected static R_VAL BuildReturnValue(RubyState state, List <int> outParams, object[] pars, object retv) { if (outParams == null) { return(RubyState.ObjectToValue(state, retv)); } else { R_VAL[] rets = new R_VAL[outParams.Count + 1]; if (retv is R_VAL && R_VAL.IsNil(( R_VAL )retv)) { rets[0] = R_VAL.NIL; } else { rets[0] = RubyState.ObjectToValue(state, retv); } for (int i = 0; i < outParams.Count; i++) { rets[i + 1] = RubyState.ObjectToValue(state, pars[outParams[i]]); } R_VAL ary = RubyDLL.r_ary_new(); foreach (var p in rets) { RubyDLL.r_ary_push(state, ary, p); } return(ary); } }
public R_VAL ExecuteSet(RubyState state, object obj, CallbackArguments args) { var arg = args.RawGet(0, false); FieldInfo.SetValue(obj, RubyState.ValueToObjectOfType(state, arg, DataTypePtr, FieldInfo.FieldType, FieldInfo.FieldType, false)); return(R_VAL.NIL); }
public mRubyModule(RubyState state, string name) { this.name = name; this.state = state; this.module_ptr = RubyDLL.r_define_module(state.rb_state, name); this.module_value = R_VAL.CreateOBJ(module_ptr); }
public static ObjectTranslator Get(IntPtr mrbState) { #if !MULTI_STATE return(_translator); #else return(RubyState.GetTranslator(mrbState)); #endif }
/// <summary> /// 定义一个新Class,默认继承自mruby的Object /// </summary> public mRubyClass(RubyState state, string name) { mRubyClass.RegisteredClass.Add(name, this); this.name = name; this.state = state; this.class_ptr = RubyDLL.r_define_class(state, name, state.rb_object_class); this.class_value = R_VAL.CreateOBJ(class_ptr); }
public static void RegByNamespace(RubyState state, Assembly assembly, string @namespace) { Type[] types = assembly.GetTypes() .Where(t => String.Equals(t.Namespace, @namespace, StringComparison.Ordinal)) .ToArray(); foreach (var type in types) { GenCSharpClass(type); } }
public static void RegisterEnum <T> (RubyState state) { Type type = typeof(T); IntPtr module = UserDataUtility.DefineCSharpEnum(state, type); foreach (int i in System.Enum.GetValues(type)) { RubyDLL.r_define_const(state, module, System.Enum.GetName(type, i), RubyDLL.mrb_fixnum_value(state, i)); } }
public static void RegisterType <T> (RubyState state) { Type type = typeof(T); if (type.IsEnum) { RegisterEnum <T> (state); return; } RegisterClass <T> (state); }
/// <summary> /// DefineCSharpClass in ruby and set data type /// </summary> /// <param name="state"></param> /// <param name="type"></param> /// <returns></returns> public static IntPtr DefineCSharpClass(RubyState state, Type type) { // 模块和类的开头必须是大写字母 IntPtr @class = IntPtr.Zero; string[] namespacePath = type.FullName.Split('.'); if (namespacePath.Length == 1) { @class = RubyDLL.r_define_class(state, type.Name, state.SystemObjectRClass); } else { foreach (var name in namespacePath) { string validName = name; // 检查命名开头字母大小写 if (!char.IsUpper(name[0])) { char head = char.ToUpper(name[0]); string newName = name; newName = name.Remove(0, 1); newName = newName.Insert(0, head.ToString()); Console.WriteLine($"{name} -> {newName}"); validName = newName; } if (name.Equals(namespacePath[0])) { @class = RubyDLL.r_define_module(state, validName); RubyDLL.mrb_set_instance_tt(@class, rb_vtype.RUBY_T_DATA); } else if (name.Equals(namespacePath[namespacePath.Length - 1])) { @class = RubyDLL.r_define_class_under(state, @class, validName, state.SystemObjectRClass); RubyDLL.mrb_set_instance_tt(@class, rb_vtype.RUBY_T_DATA); } else { @class = RubyDLL.r_define_module_under(state, @class, validName, IntPtr.Zero); RubyDLL.mrb_set_instance_tt(@class, rb_vtype.RUBY_T_DATA); } } } return(@class); }
/// <summary> /// Invokes the callback function /// </summary> /// <param name="executionContext">The execution context.</param> /// <param name="args">The arguments.</param> /// <param name="isMethodCall">if set to <c>true</c> this is a method call.</param> /// <returns></returns> public R_VAL Invoke(RubyState state, R_VAL self) { #if DEBUG try { #endif return(ClrCallback(state, Target, new CallbackArguments(RubyDLL.GetFunctionArgs(state)))); #if DEBUG } catch (Exception e) { Console.WriteLine($"Exception on CallbackFunction::Invoke() {Name}\n{e.Message}"); throw; } #endif }
public R_VAL Invoke(RubyState state, int argc, R_VAL[] argv, R_VAL self) { #if DEBUG try { #endif #if MRUBY return(ClrCallback(state, Target, new CallbackArguments(RubyDLL.GetFunctionArgs(state)))); #else return(ClrCallback(state, Target, new CallbackArguments(argv))); #endif #if DEBUG } catch (Exception e) { Console.WriteLine($"Exception on CallbackFunction::Invoke() {Name}"); throw; } #endif }
/// <summary> /// The internal callback which actually executes the method /// </summary> /// <param name="script">The script.</param> /// <param name="obj">The object.</param> /// <param name="context">The context.</param> /// <param name="args">The arguments.</param> /// <returns></returns> public override R_VAL Execute(RubyState state, object obj, CallbackArguments args) { // if ( AccessMode == InteropAccessMode.LazyOptimized && // m_OptimizedFunc == null && m_OptimizedAction == null ) // ( ( IOptimizableDescriptor )this ).Optimize (); List <int> outParams; object[] pars = base.BuildArgumentList(state, obj, args, out outParams); object retv; if (m_OptimizedFunc != null) { retv = m_OptimizedFunc(obj, pars); } else if (m_OptimizedAction != null) { m_OptimizedAction(obj, pars); retv = R_VAL.NIL; } else if (m_IsAction) { MethodInfo.Invoke(obj, pars); retv = R_VAL.NIL; } else { if (IsConstructor) { retv = (( ConstructorInfo )MethodInfo).Invoke(pars); } else { retv = MethodInfo.Invoke(obj, pars); } } return(BuildReturnValue(state, outParams, pars, retv)); }
/// <summary> /// Builds the return value of a call /// </summary> /// <param name="outParams">The out parameters indices, or null. See <see cref="BuildArgumentList" />.</param> /// <param name="pars">The parameters passed to the function.</param> /// <param name="retv">The return value from the function. Use DynValue.Void if the function returned no value.</param> /// <returns>A DynValue to be returned to scripts</returns> protected static R_VAL BuildReturnValue(RubyState state, object retv) { return(RubyState.ObjectToValue(state, retv)); }
/// <summary> /// Builds the argument list. /// </summary> /// <param name="state">The ruby state.</param> /// <param name="obj">The object.</param> /// <param name="args">The arguments.</param> /// <param name="outParams">Output: A list containing the indices of all "out" parameters, or null if no out parameters are specified.</param> /// <returns>The arguments, appropriately converted.</returns> protected virtual object[] BuildArgumentList(RubyState state, object obj, CallbackArguments args, out List <int> outParams) { ParameterDescriptor[] parameters = Parameters; object[] pars = new object[parameters.Length]; int j = args.IsMethodCall ? 1 : 0; outParams = null; for (int i = 0; i < pars.Length; i++) { // keep track of out and ref params if (parameters[i].Type.IsByRef) { if (outParams == null) { outParams = new List <int> (); } outParams.Add(i); } // if an ext method, we have an obj -> fill the first param if (ExtensionMethodType != null && obj != null && i == 0) { pars[i] = obj; continue; } else if (parameters[i].Type == typeof(CallbackArguments)) { pars[i] = args.SkipMethodCall(); } // else, ignore out params else if (parameters[i].IsOut) { pars[i] = null; } else if (i == parameters.Length - 1 && VarArgsArrayType != null) { List <R_VAL> extraArgs = new List <R_VAL> (); while (true) { var arg = args.RawGet(j, false); j += 1; if (!R_VAL.IsNil(arg)) { extraArgs.Add(arg); } else { break; } } // here we have to worry we already have an array.. damn. We only support this for userdata. // remains to be analyzed what's the correct behavior here. For example, let's take a params object[].. // given a single table parameter, should it use it as an array or as an object itself ? if (extraArgs.Count == 1) { R_VAL arg = extraArgs[0]; if (R_VAL.IsData(arg)) { // if ( Framework.Do.IsAssignableFrom ( VarArgsArrayType, arg.UserData.Object.GetType () ) ) { // pars[ i ] = RubyDLL.ValueToDataObject< object > ( state, arg, RubyState.DATA_TYPE_PTR ); pars[i] = RubyState.ValueToRefObject(state, arg, DataTypePtr); continue; // } } } // ok let's create an array, and loop Array vararg = Array.CreateInstance(VarArgsElementType, extraArgs.Count); for (int ii = 0; ii < extraArgs.Count; ii++) { vararg.SetValue(RubyState.ValueToObjectOfType(state, extraArgs[ii], DataTypePtr, VarArgsElementType, null, false), ii); } pars[i] = vararg; } // else, convert it else { var arg = args.RawGet(j, false); pars[i] = RubyState.ValueToObjectOfType(state, arg, DataTypePtr, parameters[i].Type, parameters[i].DefaultValue, parameters[i].HasDefaultValue); j += 1; } } return(pars); }
/// <summary> /// The internal callback which actually executes the method /// </summary> /// <param name="obj">The object.</param> /// <param name="args">The arguments.</param> /// <returns></returns> public R_VAL ExecuteGet(RubyState state, object obj, CallbackArguments args) { return(RubyState.ObjectToValue(state, FieldInfo.GetValue(obj))); }
static void Main() { // https://github.com/FNA-XNA/FNA/wiki/4:-FNA-and-Windows-API#64-bit-support if (Environment.OSVersion.Platform == PlatformID.Unix) { string path = Environment.GetEnvironmentVariable("PATH"); Environment.SetEnvironmentVariable("PATH", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lib", "osx") + ";" + path); // string libPath = Environment.GetEnvironmentVariable ( "LD_LIBRARY_PATH" ); // Environment.SetEnvironmentVariable ( "LD_LIBRARY_PATH", Path.Combine ( AppDomain.CurrentDomain.BaseDirectory, "lib", "osx" ) + ";" + libPath ); } // Console.WriteLine ( (GC.GetTotalMemory(false) / 1048576f).ToString("F") + " MB" ); state = new RubyState(); state.DoString("puts \"ruby #{RUBY_VERSION}\""); // Console.WriteLine ( (GC.GetTotalMemory(false) / 1048576f).ToString("F") + " MB" ); #if MRUBY R_VAL v1 = R_VAL.Create(state, 2333); R_VAL v2 = R_VAL.Create(state, 3.1415926535897932f); #else R_VAL v1 = R_VAL.Create(2333); R_VAL v2 = R_VAL.Create(3.1415926535897932d); #endif R_VAL v3 = R_VAL.FALSE; R_VAL v4 = R_VAL.TRUE; R_VAL v5 = R_VAL.NIL; #if MRUBY Console.WriteLine(v1.ToString(state)); Console.WriteLine(v2.ToString(state)); Console.WriteLine(v3.ToString(state)); Console.WriteLine(v4.ToString(state)); Console.WriteLine(v5.ToString(state)); state.DefineMethod("WriteLine", WriteLine, rb_args.ANY()); state.DefineMethod("show_backtrace", ShowBackTrace, rb_args.NONE()); state.DefineMethod("WriteLineNormal", new System.Action <string, int, float, bool> (TestDelegate), rb_args.ANY()); mRubyClass klass = new mRubyClass(state, "CSharpClass"); klass.DefineMethod("write", WriteLine, rb_args.ANY()); // WrapperUtility.GenCSharpClass ( typeof ( System.Object ) ); // WrapperUtility.GenCSharpClass ( typeof ( System.Array ) ); // WrapperUtility.GenCSharpClass ( typeof ( System.TimeSpan ) ); // WrapperUtility.GenByAssembly ( typeof ( Microsoft.Xna.Framework.Game ).Assembly ); // WrapperUtility.GenUnityEngineCommon (); // WrapperUtility.GenCSharpClass ( typeof ( CustomClass ) ); // WrapperUtility.GenCSharpClass ( typeof ( CustomEnum ) ); UserDataUtility.RegisterType <CustomClass> (state); UserDataUtility.RegisterType <CustomEnum> (state); // CustomClass_Wrapper.__Register__ ( state ); // CustomEnum_Wrapper.__Register__ ( state ); // state.DoFile ( "main.rb" ); #else Console.WriteLine(v1.ToString()); Console.WriteLine(v2.ToString()); Console.WriteLine(v3.ToString()); Console.WriteLine(v4.ToString()); Console.WriteLine(v5.ToString()); state.DefineMethod("WriteLine", WriteLine, rb_args.ANY()); state.DefineMethod("show_backtrace", ShowBackTrace, rb_args.NONE()); #endif state.DoString("WriteLine(\"System::Object.new\")"); state.DoString("show_backtrace"); state.DoString("WriteLineNormal( 'mruby ok!', 1, 9.9, true )"); state.DoString("puts RubySharp::CustomEnum::A"); state.DoString("puts RubySharp::CustomEnum::B"); state.DoString("puts RubySharp::CustomEnum::C"); state.DoString("puts RubySharp::CustomClass.new.FuncB( 999 )"); state.DoString("puts RubySharp::CustomClass.new.FuncC( 'AABB' )"); state.DoString("puts RubySharp::CustomClass.new.FuncD( 1, 2.0, true, 'HelloString', RubySharp::CustomClass.new )"); state.DoString("puts RubySharp::CustomClass.+( RubySharp::CustomClass.new, 100 )"); state.DoString("puts RubySharp::CustomClass::FuncE( nil )"); state.DoString("puts RubySharp::CustomClass.FuncF( RubySharp::CustomClass.new, 900.0 )"); state.DoString("puts RubySharp::CustomClass.new.FuncG( RubySharp::CustomClass.new )"); #if MRUBY if (RubyDLL.mrb_has_exc(state)) { Console.WriteLine(state.GetExceptionBackTrace()); RubyDLL.mrb_exc_clear(state); } #else R_VAL exc = RubyDLL.rb_errinfo(); if (RubyDLL.r_type(exc) != rb_vtype.RUBY_T_NIL) { Console.WriteLine(RubyState.GetExceptionBackTrace()); } #endif (state as IDisposable).Dispose(); // Console.ReadKey (); }
/// <summary> /// The internal callback which actually executes the method /// </summary> /// <param name="obj">The object.</param> /// <param name="context">The context.</param> /// <param name="args">The arguments.</param> /// <returns></returns> public abstract R_VAL Execute(RubyState state, object obj, CallbackArguments args);
/// <summary> /// The internal callback which actually executes the method /// </summary> /// <param name="script">The script.</param> /// <param name="obj">The object.</param> /// <param name="context">The context.</param> /// <param name="args">The arguments.</param> /// <returns></returns> public R_VAL ExecuteGet(RubyState state, object obj, CallbackArguments args) { return(RubyState.ObjectToValue(state, PropertyInfo.GetValue(obj, null))); }
public static void RegisterClass <T> (RubyState state) { Type type = typeof(T); IntPtr @class = UserDataUtility.DefineCSharpClass(state, type); mrb_data_type dataType = RubyState.ObjectDataType; IntPtr dataTypePtr = RubyState.ObjectDataTypePtr; // state.AffirmDataTypeStruct< T >( out dataType, out dataTypePtr ); state.AddRegistedTypeInfo <T>(@class, dataType, dataTypePtr); RegistedTypeInfo registedTypeInfo = state.GetRegistedTypeInfo(type); Dictionary <string, RubyDLL.RubyCSFunction> instanceFunction = new Dictionary <string, RubyDLL.RubyCSFunction> (); Dictionary <string, RubyDLL.RubyCSFunction> classFunction = new Dictionary <string, RubyDLL.RubyCSFunction> (); // Reg Ctor if (!type.IsAbstract || !type.IsSealed) { ConstructorInfo publicCtor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance).OrderBy(c => c.GetParameters().Length).FirstOrDefault(); if (publicCtor != null) { // CallbackFunction function = CallbackFunction.FromMethodInfo ( publicCtor ); RubyDLL.RubyCSFunction rubyFunction = (mrb, self) => { // T obj = RubyDLL.ValueToDataObject< T > ( mrb, function.Invoke ( state, self ), RubyState.DATA_TYPE_PTR ); // RubyDLL.mrb_data_init ( self, RubyDLL.ObjectToInPtr ( obj ), RubyState.DATA_TYPE_PTR ); object obj = Activator.CreateInstance(type, RubyState.RubyFunctionParamsToObjects(mrb, dataTypePtr)); RubyDLL.mrb_data_init(self, state.PushRegistedCSharpObject(obj), dataTypePtr); // 添加实例映射 state.AddCRInstanceMap(obj, self); return(self); }; RubyDLL.r_define_method(state, @class, "initialize", rubyFunction, rb_args.REQ((uint)publicCtor.GetParameters().Length)); registedTypeInfo.ctorFunction = rubyFunction; } } // Reg Public Field Get Set IList <FieldInfo> publicFields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (var field in publicFields) { // skip Obsolete if (field.IsDefined(typeof(System.ObsoleteAttribute), false)) { continue; } if (!TestTypeSupport(field.FieldType)) { continue; } CallbackFunction getFunc = CallbackFunction.FromFieldInfo_Get(field, dataTypePtr); CallbackFunction setFunc = CallbackFunction.FromFieldInfo_Set(field, dataTypePtr); RubyDLL.RubyCSFunction getFunction = (mrb, self) => { // T obj = RubyDLL.ValueToDataObject< T > ( mrb, self, dataTypePtr ); object obj = RubyState.ValueToRefObject(state, self, dataTypePtr); return(getFunc.SetCallbackTarget(obj).Invoke(state, self)); }; RubyDLL.r_define_method(state, @class, field.Name, getFunction, rb_args.NONE()); instanceFunction.Add(field.Name, getFunction); if (setFunc != null) { RubyDLL.RubyCSFunction setFunction = (mrb, self) => { // T obj = RubyDLL.ValueToDataObject< T > ( mrb, self, dataTypePtr ); object obj = RubyState.ValueToRefObject(state, self, dataTypePtr); return(setFunc.SetCallbackTarget(obj).Invoke(state, self)); }; RubyDLL.r_define_method(state, @class, $"{field.Name}=", setFunction, rb_args.REQ(1)); instanceFunction.Add($"{field.Name}=", setFunction); } } // Reg Public Field Get Set IList <PropertyInfo> publicPropertys = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in publicPropertys) { // skip Obsolete if (property.IsDefined(typeof(System.ObsoleteAttribute), false)) { continue; } if (!TestTypeSupport(property.PropertyType)) { continue; } CallbackFunction getFunc = CallbackFunction.FromPropertyInfo_Get(property, dataTypePtr); CallbackFunction setFunc = CallbackFunction.FromPropertyInfo_Set(property, dataTypePtr); if (getFunc != null) { RubyDLL.RubyCSFunction getFunction = (mrb, self) => { // T obj = RubyDLL.ValueToDataObject< T > ( mrb, self, dataTypePtr ); object obj = RubyState.ValueToRefObject(state, self, dataTypePtr); return(getFunc.SetCallbackTarget(obj).Invoke(state, self)); }; RubyDLL.r_define_method(state, @class, property.Name, getFunction, rb_args.NONE()); instanceFunction.Add(property.Name, getFunction); } if (setFunc != null) { RubyDLL.RubyCSFunction setFunction = (mrb, self) => { // T obj = RubyDLL.ValueToDataObject< T > ( mrb, self, dataTypePtr ); object obj = RubyState.ValueToRefObject(state, self, dataTypePtr); return(setFunc.SetCallbackTarget(obj).Invoke(state, self)); }; RubyDLL.r_define_method(state, @class, $"{property.Name}=", setFunction, rb_args.REQ(1)); instanceFunction.Add($"{property.Name}=", setFunction); } } // Gen Wrap Function IList <MethodInfo> publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(m => !m.IsSpecialName).ToArray(); foreach (var method in publicMethods) { if (!TestFunctionSupport(method)) { Console.WriteLine($"{type.Name}.{method.Name} not support."); continue; } // TODO: 支持方法重载?? // if ( generatedMethods.ContainsKey ( method.Name ) ) { // continue; // } if (instanceFunction.ContainsKey(method.Name)) { continue; } CallbackFunction function = CallbackFunction.FromMethodInfo(method, dataTypePtr); RubyDLL.RubyCSFunction rubyFunction = (mrb, self) => { // T obj = RubyDLL.ValueToDataObject< T > ( mrb, self, dataTypePtr ); object obj = RubyState.ValueToRefObject(state, self, dataTypePtr); return(function.SetCallbackTarget(obj).Invoke(state, self)); }; RubyDLL.r_define_method(state, @class, method.Name, rubyFunction, rb_args.ANY()); instanceFunction.Add(method.Name, rubyFunction); } IList <MethodInfo> publicStaticMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(m => !m.IsSpecialName).ToArray(); foreach (var method in publicStaticMethods) { if (!TestFunctionSupport(method)) { Console.WriteLine($"{type.Name}.{method.Name} not support."); continue; } // TODO: 支持方法重载?? // if ( generatedMethods.ContainsKey ( method.Name ) ) { // continue; // } if (classFunction.ContainsKey(method.Name)) { continue; } CallbackFunction function = CallbackFunction.FromMethodInfo(method, dataTypePtr); RubyDLL.RubyCSFunction rubyFunction = (mrb, self) => { return(function.Invoke(state, self)); }; RubyDLL.r_define_class_method(state, @class, method.Name, rubyFunction, rb_args.ANY()); classFunction.Add(method.Name, rubyFunction); } // Reg Operator Function Static ?? // 当前可以注册为ruby类方法问题,运算符在ruby中是实例方法,在C#中是静态方法 foreach (var kv in operator_methods) { var methodInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(m => { if (!m.Name.Equals(kv.Key)) { return(false); } var parameters = m.GetParameters(); if (parameters.Length != 2) { return(false); } if (parameters[0].ParameterType != type) { return(false); } return(true); }).FirstOrDefault(); if (methodInfo == null) { continue; } if (!TestTypeSupport(methodInfo.GetParameters()[1].ParameterType)) { continue; } CallbackFunction function = CallbackFunction.FromMethodInfo(methodInfo, dataTypePtr); RubyDLL.RubyCSFunction rubyFunction = (mrb, self) => { return(function.Invoke(state, self)); }; RubyDLL.r_define_class_method(state, @class, kv.Value, rubyFunction, rb_args.REQ(1)); classFunction.Add(kv.Value, rubyFunction); } registedTypeInfo.instanceFunction = instanceFunction; registedTypeInfo.classFunction = classFunction; }
public static IntPtr DefineCSharpClass <T> (RubyState state) { Type type = typeof(T); return(DefineCSharpClass(state, type)); }