示例#1
0
        public void AffirmDataTypeStruct <T> (out mrb_data_type data_type_t, out IntPtr data_type_ptr)
        {
            data_type_t   = default;
            data_type_ptr = IntPtr.Zero;

            Type type = typeof(T);

            // Use exist
            if (registedDataTypeDictionary.ContainsKey(type))
            {
                data_type_t = registedDataTypeDictionary[type];

                if (registedDataTypePtrDictionary.ContainsKey(type))
                {
                    data_type_ptr = registedDataTypePtrDictionary[type];
                }
                return;
            }

            // Create new
            AllocDataTypeStruct(type.FullName, out data_type_t, out data_type_ptr);

            registedDataTypeDictionary.Add(type, data_type_t);
            registedDataTypePtrDictionary.Add(type, data_type_ptr);
        }
示例#2
0
 public void AddRegistedTypeInfo <T> (IntPtr @class, mrb_data_type dataType, IntPtr dataTypePtr)
 {
     registedTypeInfoDictionary.Add(typeof(T),
                                    new RegistedTypeInfo()
     {
         @class = @class, dataType = dataType, dataTypePtr = dataTypePtr
     });
 }
示例#3
0
        private void AllocDataTypeStruct(string structName, out mrb_data_type data_type_t, out IntPtr data_type_ptr)
        {
            data_type_t = new mrb_data_type {
                struct_name = structName,
                dfree       = DFree
            };

            data_type_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(data_type_t));
            Marshal.StructureToPtr(data_type_t, data_type_ptr, false);
        }
        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;
        }