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);
        }
Example #4
0
 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);
 }
Example #5
0
        public static ObjectTranslator Get(IntPtr mrbState)
        {
#if !MULTI_STATE
            return(_translator);
#else
            return(RubyState.GetTranslator(mrbState));
#endif
        }
Example #6
0
        /// <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);
        }
Example #7
0
 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
        }
Example #13
0
        /// <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)));
 }
Example #17
0
        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));
        }