private static void GenGetSetInstancePropertyBody(string className, PropertyInfo propertyInfo, StringBuilder builder) { UserDataUtility.TestPropertyCanAccess(propertyInfo, out var getterCanAccess, out var setterCanAccess); // Get if (propertyInfo.CanRead && getterCanAccess) { builder.AppendFormat($"\t\t{RUBYSHARP_WrapFunction}" + " {{\n", propertyInfo.Name); builder.AppendFormat($"\t\t\t{RUBYSHARP_ValueToCSInstance}\n", className); builder.AppendLine($"\t\t\treturn {GenCSObjectToValue ( propertyInfo.PropertyType, $"instance.{propertyInfo.Name}" )};"); builder.AppendLine("\t\t}\n"); } // Set if (propertyInfo.CanWrite && setterCanAccess) { builder.AppendFormat($"\t\t{RUBYSHARP_WrapFunction}" + " {{\n", $"{propertyInfo.Name}{RUBYSHARP_FIELD_SET_FUNCTION_POSTFIX}"); builder.AppendFormat($"\t\t\t{RUBYSHARP_ValueToCSInstance}\n", className); builder.AppendLine("\t\t\tR_VAL[] args = RubyDLL.GetFunctionArgs ( mrb );"); builder.AppendLine(); GenCheckParamCount(className, propertyInfo, builder); GenCheckParamsType(className, propertyInfo, builder); builder.AppendLine($"\t\t\tinstance.{propertyInfo.Name} = {GenValueToCSObject ( propertyInfo.PropertyType, "args[ 0 ]" )};"); builder.AppendLine($"\t\t\treturn self;"); builder.AppendLine("\t\t}\n"); } }
public static CallbackFunction FromPropertyInfo_Set(System.Reflection.PropertyInfo property, IntPtr dataTypePtr) { PropertyDescriptor descr = new PropertyDescriptor(property); descr.DataTypePtr = dataTypePtr; UserDataUtility.TestPropertyCanAccess(property, out var canGet, out var canSet); return(canSet ? descr.GetSetCallbackFunction() : null); }
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)); } }
internal void InitBaseTypeBinding() { #if MRUBY // SystemObjectRClass = UserDataUtility.DefineCSharpClass ( this, typeof ( System.Object ) ); AffirmDataTypeStruct <System.Object> (out _ObjectDataType, out _ObjectDataTypePtr); AffirmDataTypeStruct <System.Enum> (out _EnumDataType, out _EnumDataTypePtr); UserDataUtility.RegisterClass <System.Object> (this); SystemObjectRClass = GetRegistedTypeInfo <System.Object> ().@class; UserDataUtility.RegisterClass <System.Type> (this); // UserDataUtility.RegisterClass< System.Array > ( this ); UserDataUtility.RegisterClass <System.Delegate> (this); #endif }
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 (); }
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 void GenCSharpClassSourceCode(Type type, StringBuilder builder) { string wrapperClassName = GetShortWrapperClassName(type); bool hasNamespace = type.FullName.Split('.').Length != 1; // key: name in ruby | value: name in C# Dictionary <string, string> generatedMethods = new Dictionary <string, string>(); Dictionary <string, string> generatedClassMethods = new Dictionary <string, string>(); // Gen Using builder.AppendLine("using System;"); builder.AppendLine("using System.Runtime.InteropServices;"); builder.AppendLine("using RubySharp;"); builder.AppendLine(); // Gen Namespace and Class Sign if (hasNamespace) { builder.AppendLine("namespace " + type.Namespace + " {"); builder.AppendLine(); } builder.AppendLine("\tpublic class " + wrapperClassName + " {"); builder.AppendLine(); // Gen Data Type Struct builder.AppendLine("\t\tpublic static readonly mrb_data_type data_type = new mrb_data_type () {"); builder.AppendLine($"\t\t\tstruct_name = \"{type.Name}\","); builder.AppendLine("\t\t\tdfree = null"); builder.AppendLine("\t\t};"); builder.AppendLine(); // Gen Dep Static Field builder.AppendLine($"\t\tpublic static IntPtr {RUBYSHARP_FIELD_RClassVarName};"); builder.AppendLine($"\t\tpublic static IntPtr {RUBYSHARP_FIELD_DataTypePtrVarName};"); builder.AppendLine($"\t\tpublic static RubyState {RUBYSHARP_FIELD_MRubyStateVarName};"); builder.AppendLine(); // Gen Ctor Function // TODO: 支持有参数构造方法 if (!type.IsAbstract || !type.IsSealed) { ConstructorInfo publicCtor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance).Where(c => c.GetParameters().Length == 0).FirstOrDefault(); if (publicCtor != null) { builder.AppendFormat($"\t\t{RUBYSHARP_WrapFunction}" + " {{\n", "initialize"); builder.AppendFormat("\t\t\t{0} instance = new {0} ();\n", type.Name); // builder.AppendLine ( $"\t\t\tRubyDLL.mrb_data_init ( self, RubyDLL.ObjectToInPtr ( instance ), data_type_ptr );" ); builder.AppendLine($"\t\t\tRubyDLL.mrb_data_init ( self, RubyDLL.ObjectToInPtr ( instance ), {RUBYSHARP_COMMON_DATA_TYPE_PTR} );"); builder.AppendLine($"\t\t\treturn self;"); builder.AppendLine("\t\t}\n"); generatedMethods.Add("initialize", "initialize"); } } // Gen Public Field Get Set IList <FieldInfo> publicFields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (var field in publicFields) { if (ignored_fields.Contains(field.Name)) { continue; } // skip Obsolete if (field.IsDefined(typeof(System.ObsoleteAttribute), false)) { continue; } if (!TestTypeSupport(field.FieldType)) { continue; } GenGetSetInstanceFieldBody(type.Name, field, builder); if (!generatedMethods.ContainsKey(field.Name)) { generatedMethods.Add(field.Name, field.Name); if (!field.IsInitOnly) { generatedMethods.Add($"{field.Name}=", $"{field.Name}{RUBYSHARP_FIELD_SET_FUNCTION_POSTFIX}"); } } } // Gen Public Field Get Set IList <PropertyInfo> publicPropertys = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in publicPropertys) { if (ignored_fields.Contains(property.Name)) { continue; } // skip Obsolete if (property.IsDefined(typeof(System.ObsoleteAttribute), false)) { continue; } if (!TestTypeSupport(property.PropertyType)) { continue; } GenGetSetInstancePropertyBody(type.Name, property, builder); if (!generatedMethods.ContainsKey(property.Name)) { UserDataUtility.TestPropertyCanAccess(property, out var getterCanAccess, out var setterCanAccess); if (property.CanRead && getterCanAccess) { generatedMethods.Add(property.Name, property.Name); } if (property.CanWrite && setterCanAccess) { generatedMethods.Add($"{property.Name}=", $"{property.Name}{RUBYSHARP_FIELD_SET_FUNCTION_POSTFIX}"); } } } // Gen Instance Function IList <MethodInfo> publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(m => !m.IsSpecialName).ToArray(); foreach (var method in publicMethods) { if (ignored_methods.Contains(method.Name)) { continue; } if (!TestFunctionSupport(method)) { Console.WriteLine($"{type.Name}.{method.Name} not support."); continue; } // TODO: 支持方法重载?? if (generatedMethods.ContainsKey(method.Name)) { continue; } GenInstanceBindingFunctionBody(type, string.Empty, method, builder); generatedMethods.Add(method.Name, method.Name); } // Gen Static Function IList <MethodInfo> publicStaticMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(m => !m.IsSpecialName).ToArray(); foreach (var method in publicStaticMethods) { if (ignored_methods.Contains(method.Name)) { continue; } if (!TestFunctionSupport(method)) { Console.WriteLine($"{type.Name}::{method.Name} not support."); continue; } // TODO: 支持方法重载?? if (generatedClassMethods.ContainsKey(method.Name)) { continue; } string staticMethodName = $"{RUBYSHARP_STATIC_FUNCTION_PREFIX}{method.Name}"; GenStaticBindingFunctionBody(type.Name, method.Name, method, builder); generatedClassMethods.Add(method.Name, staticMethodName); } // Gen Operator Function foreach (var kv in operator_methods) { bool result = Gen_OpFunction_IfExist(type, kv.Key, builder); if (result) { generatedMethods.Add(kv.Value, $"_{kv.Key}"); } } // Gen Static Register function builder.AppendLine("\t\tpublic static void " + RUBYSHARP_StaticRegisterFunctionName + " ( RubyState state ) {"); builder.AppendLine($"\t\t\t{wrapperClassName}.state = state;"); builder.AppendLine($"\t\t\t{wrapperClassName}.@class = UserDataUtility.DefineCSharpClass ( state, typeof ( {type.FullName} ) );"); builder.AppendLine($"\t\t\t{wrapperClassName}.data_type_ptr = RubyDLL.ObjectToInPtr ( {RUBYSHARP_FIELD_DataTypePtrVarName} );"); builder.AppendLine(); foreach (var kv in generatedMethods) { builder.AppendLine($"\t\t\tRubyDLL.mrb_define_method ( state, @class, \"{kv.Key}\", {kv.Value}, mrb_args.ANY () );"); } builder.AppendLine(); foreach (var kv in generatedClassMethods) { builder.AppendLine($"\t\t\tRubyDLL.mrb_define_class_method ( state, @class, \"{kv.Key}\", {kv.Value}, mrb_args.ANY () );"); } builder.AppendLine("\t\t}"); // Gen End builder.AppendLine("\t}"); if (hasNamespace) { builder.AppendLine("}"); } File.WriteAllText($"{type.FullName.Replace ( ".", "_" )}{RUBYSHARP_WRAPPERCLASS_POSTFIX}.cs", builder.ToString()); // DEBUG // Console.WriteLine ( builder.ToString () ); }