public void DefineStaticMethod(string name, RubyDLL.RubyCSFunction receiver, rb_args aspec)
        {
            // 防止被C#端GC
            state.MethodDelegates.Add(receiver);

            RubyDLL.r_define_class_method(state, class_ptr, name, receiver, aspec);
        }
        public void DefineMethod(string name, RubyDLL.RubyCSFunction receiver, rb_args aspec)
        {
            // 防止被C#端GC
            state.MethodDelegates.Add(receiver);

            RubyDLL.r_define_module_function(state.rb_state, module_ptr, name, receiver, aspec);
        }
Exemple #3
0
        /// <summary>
        /// 在mruby全局中定义方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="delegate">实例方法/静态方法</param>
        /// <param name="aspec"></param>
        public void DefineMethod(string name, Delegate @delegate, rb_args aspec)
        {
            var function = CallbackFunction.FromDelegate(@delegate, RubyState.ObjectDataTypePtr);
            var method   = new RubyDLL.RubyCSFunction((state, self) => function.Invoke(this, self));

            // 防止被C#端GC
            MethodDelegates.Add(method);

#if MRUBY
            RubyDLL.r_define_module_function(rb_state, rb_kernel_module, name, method, aspec);
#else
            RubyDLL.r_define_module_function(rb_kernel_module, name, method, aspec);
#endif
        }
Exemple #4
0
        /// <summary>
        /// 在mruby全局中定义方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="receiver"></param>
        /// <param name="aspec"></param>
        public void DefineMethod(string name, RubyDLL.RubyCSFunction receiver, rb_args aspec)
        {
            // 防止被C#端GC
            MethodDelegates.Add(receiver);

#if MRUBY
            RubyDLL.r_define_module_function(rb_state, rb_kernel_module, name, receiver, aspec);
#else
            // RubyDLL.RubyCSFunction receiverDelegate = receiver;
            // GCHandle gch = GCHandle.Alloc(receiverDelegate);
            // IntPtr intptr_delegate = Marshal.GetFunctionPointerForDelegate(receiverDelegate);
            RubyDLL.r_define_module_function(rb_kernel_module, name, receiver, aspec.value);
#endif
        }
        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;
        }