GetTypeByAlias() статический приватный Метод

static private GetTypeByAlias ( IntPtr op ) : Type
op System.IntPtr
Результат System.Type
Пример #1
0
        //====================================================================
        // Implementation of [] semantics for reflected types. This mainly
        // exists to implement the Array[int] syntax for creating arrays.
        //====================================================================

        public override IntPtr type_subscript(IntPtr ob, IntPtr idx)
        {
            if ((this.type) != typeof(Array))
            {
                return(Exceptions.RaiseTypeError("unsubscriptable object"));
            }

            if (Runtime.PyTuple_Check(idx))
            {
                return(Exceptions.RaiseTypeError("expected single type"));
            }

            ClassBase c = GetManagedObject(idx) as ClassBase;
            Type      t = (c != null) ? c.type : Converter.GetTypeByAlias(idx);

            if (t == null)
            {
                return(Exceptions.RaiseTypeError("type expected"));
            }
            Array a = Array.CreateInstance(t, 0);

            c = ClassManager.GetClass(a.GetType());
            Runtime.Incref(c.pyHandle);
            return(c.pyHandle);
        }
Пример #2
0
        internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects)
        {
            // Given a PyObject * that is either a single type object or a
            // tuple of (managed or unmanaged) type objects, return a Type[]
            // containing the CLR Type objects that map to those types.
            IntPtr args = arg;
            var    free = false;

            if (!PyTuple_Check(arg))
            {
                args = Interop.PyTuple_New(1);
                XIncref(arg);
                Interop.PyTuple_SetItem(args, 0, arg);
                free = true;
            }

            int  n     = Interop.PyTuple_Size(args);
            var  types = new Type[n];
            Type t     = null;

            for (var i = 0; i < n; i++)
            {
                IntPtr op = Interop.PyTuple_GetItem(args, i);
                if (mangleObjects && (!PyType_Check(op)))
                {
                    op = PyObject_TYPE(op);
                }
                ManagedType mt = ManagedType.GetManagedObject(op);

                if (mt is ClassBase)
                {
                    t = ((ClassBase)mt).type;
                }
                else if (mt is CLRObject)
                {
                    object inst = ((CLRObject)mt).inst;
                    if (inst is Type)
                    {
                        t = inst as Type;
                    }
                }
                else
                {
                    t = Converter.GetTypeByAlias(op);
                }

                if (t == null)
                {
                    types = null;
                    break;
                }
                types[i] = t;
            }
            if (free)
            {
                XDecref(args);
            }
            return(types);
        }
Пример #3
0
        /// <summary>
        /// Implementation of [] semantics for reflected types. This exists
        /// both to implement the Array[int] syntax for creating arrays and
        /// to support generic name overload resolution using [].
        /// </summary>
        public override IntPtr type_subscript(IntPtr idx)
        {
            if (!type.Valid)
            {
                return(Exceptions.RaiseTypeError(type.DeletedMessage));
            }

            // If this type is the Array type, the [<type>] means we need to
            // construct and return an array type of the given element type.
            if (type.Value == typeof(Array))
            {
                if (Runtime.PyTuple_Check(idx))
                {
                    return(Exceptions.RaiseTypeError("type expected"));
                }
                var  c = GetManagedObject(idx) as ClassBase;
                Type t = c != null ? c.type.Value : Converter.GetTypeByAlias(idx);
                if (t == null)
                {
                    return(Exceptions.RaiseTypeError("type expected"));
                }
                Type      a = t.MakeArrayType();
                ClassBase o = ClassManager.GetClass(a);
                Runtime.XIncref(o.pyHandle);
                return(o.pyHandle);
            }

            // If there are generics in our namespace with the same base name
            // as the current type, then [<type>] means the caller wants to
            // bind the generic type matching the given type parameters.
            Type[] types = Runtime.PythonArgsToTypeArray(idx);
            if (types == null)
            {
                return(Exceptions.RaiseTypeError("type(s) expected"));
            }

            Type gtype = AssemblyManager.LookupTypes($"{type.Value.FullName}`{types.Length}").FirstOrDefault();

            if (gtype != null)
            {
                var g = ClassManager.GetClass(gtype) as GenericType;
                return(g.type_subscript(idx));
                //Runtime.XIncref(g.pyHandle);
                //return g.pyHandle;
            }
            return(Exceptions.RaiseTypeError("unsubscriptable object"));
        }
Пример #4
0
        //====================================================================
        // Implementation of [] semantics for reflected types. This exists
        // both to implement the Array[int] syntax for creating arrays and
        // to support generic name overload resolution using [].
        //====================================================================

        public override IntPtr type_subscript(IntPtr idx)
        {
            // If this type is the Array type, the [<type>] means we need to
            // construct and return an array type of the given element type.

            if ((this.type) == typeof(Array))
            {
                if (Runtime.PyTuple_Check(idx))
                {
                    return(Exceptions.RaiseTypeError("type expected"));
                }
                ClassBase c = GetManagedObject(idx) as ClassBase;
                Type      t = (c != null) ? c.type : Converter.GetTypeByAlias(idx);
                if (t == null)
                {
                    return(Exceptions.RaiseTypeError("type expected"));
                }
                Type      a = t.MakeArrayType();
                ClassBase o = ClassManager.GetClass(a);
                Runtime.Incref(o.pyHandle);
                return(o.pyHandle);
            }

            // If there are generics in our namespace with the same base name
            // as the current type, then [<type>] means the caller wants to
            // bind the generic type matching the given type parameters.

            Type[] types = Runtime.PythonArgsToTypeArray(idx);
            if (types == null)
            {
                return(Exceptions.RaiseTypeError("type(s) expected"));
            }

            string gname = this.type.FullName + "`" + types.Length.ToString();
            Type   gtype = AssemblyManager.LookupType(gname);

            if (gtype != null)
            {
                GenericType g = ClassManager.GetClass(gtype) as GenericType;
                return(g.type_subscript(idx));

                /*Runtime.Incref(g.pyHandle);
                 * return g.pyHandle;*/
            }
            return(Exceptions.RaiseTypeError("unsubscriptable object"));
        }
Пример #5
0
        static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution)
        {
            // this logic below handles cases when multiple overloading methods
            // are ambiguous, hence comparison between Python and CLR types
            // is necessary
            Type   clrtype = null;
            IntPtr pyoptype;

            if (needsResolution)
            {
                // HACK: each overload should be weighted in some way instead
                pyoptype = Runtime.PyObject_Type(argument);
                Exceptions.Clear();
                if (pyoptype != IntPtr.Zero)
                {
                    clrtype = Converter.GetTypeByAlias(pyoptype);
                }
                Runtime.XDecref(pyoptype);
            }

            if (clrtype != null)
            {
                var typematch = false;
                if ((parameterType != typeof(object)) && (parameterType != clrtype))
                {
                    IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType);
                    pyoptype = Runtime.PyObject_Type(argument);
                    Exceptions.Clear();
                    if (pyoptype != IntPtr.Zero)
                    {
                        if (pytype != pyoptype)
                        {
                            typematch = false;
                        }
                        else
                        {
                            typematch = true;
                            clrtype   = parameterType;
                        }
                    }
                    if (!typematch)
                    {
                        // this takes care of enum values
                        TypeCode argtypecode   = Type.GetTypeCode(parameterType);
                        TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                        if (argtypecode == paramtypecode)
                        {
                            typematch = true;
                            clrtype   = parameterType;
                        }
                    }
                    Runtime.XDecref(pyoptype);
                    if (!typematch)
                    {
                        return(null);
                    }
                }
                else
                {
                    typematch = true;
                    clrtype   = parameterType;
                }
            }
            else
            {
                clrtype = parameterType;
            }

            return(clrtype);
        }
Пример #6
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;
            int          pynargs  = Runtime.PyTuple_Size(args);
            object       arg;
            var          isGeneric      = false;
            ArrayList    defaultArgList = null;

            if (info != null)
            {
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                _methods = GetMethods();
            }
            Type clrtype;

            // TODO: Clean up
            foreach (MethodBase mi in _methods)
            {
                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                ParameterInfo[] pi         = mi.GetParameters();
                int             clrnargs   = pi.Length;
                var             match      = false;
                int             arrayStart = -1;
                var             outs       = 0;

                if (pynargs == clrnargs)
                {
                    match = true;
                }
                else if (pynargs < clrnargs)
                {
                    match          = true;
                    defaultArgList = new ArrayList();
                    for (int v = pynargs; v < clrnargs; v++)
                    {
                        if (pi[v].DefaultValue == DBNull.Value)
                        {
                            match = false;
                        }
                        else
                        {
                            defaultArgList.Add(pi[v].DefaultValue);
                        }
                    }
                }
                else if (pynargs > clrnargs && clrnargs > 0 &&
                         Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute)))
                {
                    // This is a `foo(params object[] bar)` style method
                    match      = true;
                    arrayStart = clrnargs - 1;
                }

                if (match)
                {
                    var margs = new object[clrnargs];

                    for (var n = 0; n < clrnargs; n++)
                    {
                        IntPtr op;
                        if (n < pynargs)
                        {
                            if (arrayStart == n)
                            {
                                // map remaining Python arguments to a tuple since
                                // the managed function accepts it - hopefully :]
                                op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
                            }
                            else
                            {
                                op = Runtime.PyTuple_GetItem(args, n);
                            }

                            // this logic below handles cases when multiple overloading methods
                            // are ambiguous, hence comparison between Python and CLR types
                            // is necessary
                            clrtype = null;
                            IntPtr pyoptype;
                            if (_methods.Length > 1)
                            {
                                pyoptype = IntPtr.Zero;
                                pyoptype = Runtime.PyObject_Type(op);
                                Exceptions.Clear();
                                if (pyoptype != IntPtr.Zero)
                                {
                                    clrtype = Converter.GetTypeByAlias(pyoptype);
                                }
                                Runtime.XDecref(pyoptype);
                            }


                            if (clrtype != null)
                            {
                                var typematch = false;
                                if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype))
                                {
                                    IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType);
                                    pyoptype = Runtime.PyObject_Type(op);
                                    Exceptions.Clear();
                                    if (pyoptype != IntPtr.Zero)
                                    {
                                        if (pytype != pyoptype)
                                        {
                                            typematch = false;
                                        }
                                        else
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                    }
                                    if (!typematch)
                                    {
                                        // this takes care of nullables
                                        var underlyingType = Nullable.GetUnderlyingType(pi[n].ParameterType);
                                        if (underlyingType == null)
                                        {
                                            underlyingType = pi[n].ParameterType;
                                        }
                                        // this takes care of enum values
                                        TypeCode argtypecode   = Type.GetTypeCode(underlyingType);
                                        TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                                        if (argtypecode == paramtypecode)
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                        // this takes care of implicit conversions
                                        var opImplicit = pi[n].ParameterType.GetMethod("op_Implicit", new[] { clrtype });
                                        if (opImplicit != null)
                                        {
                                            typematch = opImplicit.ReturnType == pi[n].ParameterType;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                    }
                                    Runtime.XDecref(pyoptype);
                                    if (!typematch)
                                    {
                                        margs = null;
                                        break;
                                    }
                                }
                                else
                                {
                                    typematch = true;
                                    clrtype   = pi[n].ParameterType;
                                }
                            }
                            else
                            {
                                clrtype = pi[n].ParameterType;
                            }

                            if (pi[n].IsOut || clrtype.IsByRef)
                            {
                                outs++;
                            }

                            if (!Converter.ToManaged(op, clrtype, out arg, false))
                            {
                                Exceptions.Clear();
                                margs = null;
                                break;
                            }
                            if (arrayStart == n)
                            {
                                // GetSlice() creates a new reference but GetItem()
                                // returns only a borrow reference.
                                Runtime.XDecref(op);
                            }
                            margs[n] = arg;
                        }
                        else
                        {
                            if (defaultArgList != null)
                            {
                                margs[n] = defaultArgList[n - pynargs];
                            }
                        }
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    object target = null;
                    if (!mi.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    return(new Binding(mi, target, margs, outs));
                }
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
Пример #7
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // loop to find match, return invoker w/ or /wo error
            int       pynargs = Runtime.PyTuple_Size(args);
            object    arg;
            var       isGeneric = false;
            ArrayList defaultArgList;
            Type      clrtype;
            Binding   bindingUsingImplicitConversion = null;

            var methods = info == null?GetMethods()
                              : new List <MethodInformation>(1)
            {
                new MethodInformation(info, info.GetParameters())
            };

            // TODO: Clean up
            foreach (var methodInformation in methods)
            {
                var mi = methodInformation.MethodBase;
                var pi = methodInformation.ParameterInfo;

                if (mi.IsGenericMethod)
                {
                    isGeneric = true;
                }
                int clrnargs = pi.Length;
                int arrayStart;

                if (CheckMethodArgumentsMatch(clrnargs,
                                              pynargs,
                                              pi,
                                              out arrayStart,
                                              out defaultArgList))
                {
                    var outs  = 0;
                    var margs = new object[clrnargs];
                    var usedImplicitConversion = false;

                    for (var n = 0; n < clrnargs; n++)
                    {
                        IntPtr op;
                        if (n < pynargs)
                        {
                            if (arrayStart == n)
                            {
                                // map remaining Python arguments to a tuple since
                                // the managed function accepts it - hopefully :]
                                op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
                            }
                            else
                            {
                                op = Runtime.PyTuple_GetItem(args, n);
                            }

                            // this logic below handles cases when multiple overloading methods
                            // are ambiguous, hence comparison between Python and CLR types
                            // is necessary
                            clrtype = null;
                            IntPtr pyoptype;
                            if (methods.Count > 1)
                            {
                                pyoptype = IntPtr.Zero;
                                pyoptype = Runtime.PyObject_Type(op);
                                Exceptions.Clear();
                                if (pyoptype != IntPtr.Zero)
                                {
                                    clrtype = Converter.GetTypeByAlias(pyoptype);
                                }
                                Runtime.XDecref(pyoptype);
                            }


                            if (clrtype != null)
                            {
                                var typematch = false;
                                if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype))
                                {
                                    IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType);
                                    pyoptype = Runtime.PyObject_Type(op);
                                    Exceptions.Clear();
                                    if (pyoptype != IntPtr.Zero)
                                    {
                                        if (pytype != pyoptype)
                                        {
                                            typematch = false;
                                        }
                                        else
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                    }
                                    if (!typematch)
                                    {
                                        // this takes care of nullables
                                        var underlyingType = Nullable.GetUnderlyingType(pi[n].ParameterType);
                                        if (underlyingType == null)
                                        {
                                            underlyingType = pi[n].ParameterType;
                                        }
                                        // this takes care of enum values
                                        TypeCode argtypecode   = Type.GetTypeCode(underlyingType);
                                        TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                                        if (argtypecode == paramtypecode)
                                        {
                                            typematch = true;
                                            clrtype   = pi[n].ParameterType;
                                        }
                                        // accepts non-decimal numbers in decimal parameters
                                        if (underlyingType == typeof(decimal))
                                        {
                                            clrtype   = pi[n].ParameterType;
                                            typematch = Converter.ToManaged(op, clrtype, out arg, false);
                                        }
                                        // this takes care of implicit conversions
                                        var opImplicit = pi[n].ParameterType.GetMethod("op_Implicit", new[] { clrtype });
                                        if (opImplicit != null)
                                        {
                                            usedImplicitConversion = typematch = opImplicit.ReturnType == pi[n].ParameterType;
                                            clrtype = pi[n].ParameterType;
                                        }
                                    }
                                    Runtime.XDecref(pyoptype);
                                    if (!typematch)
                                    {
                                        margs = null;
                                        break;
                                    }
                                }
                                else
                                {
                                    typematch = true;
                                    clrtype   = pi[n].ParameterType;
                                }
                            }
                            else
                            {
                                clrtype = pi[n].ParameterType;
                            }

                            if (pi[n].IsOut || clrtype.IsByRef)
                            {
                                outs++;
                            }

                            if (!Converter.ToManaged(op, clrtype, out arg, false))
                            {
                                Exceptions.Clear();
                                margs = null;
                                break;
                            }
                            if (arrayStart == n)
                            {
                                // GetSlice() creates a new reference but GetItem()
                                // returns only a borrow reference.
                                Runtime.XDecref(op);
                            }
                            margs[n] = arg;
                        }
                        else
                        {
                            if (defaultArgList != null)
                            {
                                margs[n] = defaultArgList[n - pynargs];
                            }
                        }
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    object target = null;
                    if (!mi.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    var binding = new Binding(mi, target, margs, outs);
                    if (usedImplicitConversion)
                    {
                        // lets just keep the first binding using implicit conversion
                        // this is to respect method order/precedence
                        if (bindingUsingImplicitConversion == null)
                        {
                            // in this case we will not return the binding yet in case there is a match
                            // which does not use implicit conversions, which will return directly
                            bindingUsingImplicitConversion = binding;
                        }
                    }
                    else
                    {
                        return(binding);
                    }
                }
            }

            // if we generated a binding using implicit conversion return it
            if (bindingUsingImplicitConversion != null)
            {
                return(bindingUsingImplicitConversion);
            }

            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
Пример #8
0
        internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
        {
            // Relevant function variables used post conversion
            var     isGeneric = false;
            Binding bindingUsingImplicitConversion = null;

            // If we have KWArgs create dictionary and collect them
            Dictionary <string, IntPtr> kwArgDict = null;

            if (kw != IntPtr.Zero)
            {
                var pyKwArgsCount = (int)Runtime.PyDict_Size(kw);
                kwArgDict = new Dictionary <string, IntPtr>(pyKwArgsCount);
                IntPtr keylist   = Runtime.PyDict_Keys(kw);
                IntPtr valueList = Runtime.PyDict_Values(kw);
                for (int i = 0; i < pyKwArgsCount; ++i)
                {
                    var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
                    kwArgDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
                }
                Runtime.XDecref(keylist);
                Runtime.XDecref(valueList);
            }

            // Fetch our methods we are going to attempt to match and bind too.
            var methods = info == null?GetMethods()
                              : new List <MethodInformation>(1)
            {
                new MethodInformation(info, info.GetParameters())
            };

            foreach (var methodInformation in methods)
            {
                // Relevant method variables
                var mi = methodInformation.MethodBase;
                var pi = methodInformation.ParameterInfo;

                isGeneric = mi.IsGenericMethod;
                int pyArgCount = (int)Runtime.PyTuple_Size(args);


                // Special case for operators
                bool isOperator = OperatorMethod.IsOperatorMethod(mi);
                // Binary operator methods will have 2 CLR args but only one Python arg
                // (unary operators will have 1 less each), since Python operator methods are bound.
                isOperator = isOperator && pyArgCount == pi.Length - 1;
                bool isReverse = isOperator && OperatorMethod.IsReverse((MethodInfo)mi);  // Only cast if isOperator.
                if (isReverse && OperatorMethod.IsComparisonOp((MethodInfo)mi))
                {
                    continue;  // Comparison operators in Python have no reverse mode.
                }
                // Preprocessing pi to remove either the first or second argument.
                if (isOperator && !isReverse)
                {
                    // The first Python arg is the right operand, while the bound instance is the left.
                    // We need to skip the first (left operand) CLR argument.
                    pi = pi.Skip(1).ToArray();
                }
                else if (isOperator && isReverse)
                {
                    // The first Python arg is the left operand.
                    // We need to take the first CLR argument.
                    pi = pi.Take(1).ToArray();
                }

                // Must be done after IsOperator section
                int clrArgCount = pi.Length;

                if (CheckMethodArgumentsMatch(clrArgCount,
                                              pyArgCount,
                                              kwArgDict,
                                              pi,
                                              out bool paramsArray,
                                              out ArrayList defaultArgList))
                {
                    var outs  = 0;
                    var margs = new object[clrArgCount];

                    int paramsArrayIndex       = paramsArray ? pi.Length - 1 : -1; // -1 indicates no paramsArray
                    var usedImplicitConversion = false;

                    // Conversion loop for each parameter
                    for (int paramIndex = 0; paramIndex < clrArgCount; paramIndex++)
                    {
                        IntPtr op        = IntPtr.Zero;     // Python object to be converted; not yet set
                        var    parameter = pi[paramIndex];  // Clr parameter we are targeting
                        object arg;                         // Python -> Clr argument

                        // Check our KWargs for this parameter
                        bool hasNamedParam  = kwArgDict == null ? false : kwArgDict.TryGetValue(parameter.Name, out op);
                        bool isNewReference = false;

                        // Check if we are going to use default
                        if (paramIndex >= pyArgCount && !(hasNamedParam || (paramsArray && paramIndex == paramsArrayIndex)))
                        {
                            if (defaultArgList != null)
                            {
                                margs[paramIndex] = defaultArgList[paramIndex - pyArgCount];
                            }

                            continue;
                        }

                        // At this point, if op is IntPtr.Zero we don't have a KWArg and are not using default
                        if (op == IntPtr.Zero)
                        {
                            // If we have reached the paramIndex
                            if (paramsArrayIndex == paramIndex)
                            {
                                op = HandleParamsArray(args, paramsArrayIndex, pyArgCount, out isNewReference);
                            }
                            else
                            {
                                op = Runtime.PyTuple_GetItem(args, paramIndex);
                            }
                        }

                        // this logic below handles cases when multiple overloading methods
                        // are ambiguous, hence comparison between Python and CLR types
                        // is necessary
                        Type   clrtype = null;
                        IntPtr pyoptype;
                        if (methods.Count > 1)
                        {
                            pyoptype = IntPtr.Zero;
                            pyoptype = Runtime.PyObject_Type(op);
                            Exceptions.Clear();
                            if (pyoptype != IntPtr.Zero)
                            {
                                clrtype = Converter.GetTypeByAlias(pyoptype);
                            }
                            Runtime.XDecref(pyoptype);
                        }


                        if (clrtype != null)
                        {
                            var typematch = false;

                            if ((parameter.ParameterType != typeof(object)) && (parameter.ParameterType != clrtype))
                            {
                                IntPtr pytype = Converter.GetPythonTypeByAlias(parameter.ParameterType);
                                pyoptype = Runtime.PyObject_Type(op);
                                Exceptions.Clear();
                                if (pyoptype != IntPtr.Zero)
                                {
                                    if (pytype != pyoptype)
                                    {
                                        typematch = false;
                                    }
                                    else
                                    {
                                        typematch = true;
                                        clrtype   = parameter.ParameterType;
                                    }
                                }
                                if (!typematch)
                                {
                                    // this takes care of nullables
                                    var underlyingType = Nullable.GetUnderlyingType(parameter.ParameterType);
                                    if (underlyingType == null)
                                    {
                                        underlyingType = parameter.ParameterType;
                                    }
                                    // this takes care of enum values
                                    TypeCode argtypecode   = Type.GetTypeCode(underlyingType);
                                    TypeCode paramtypecode = Type.GetTypeCode(clrtype);
                                    if (argtypecode == paramtypecode)
                                    {
                                        typematch = true;
                                        clrtype   = parameter.ParameterType;
                                    }
                                    // accepts non-decimal numbers in decimal parameters
                                    if (underlyingType == typeof(decimal))
                                    {
                                        clrtype   = parameter.ParameterType;
                                        typematch = Converter.ToManaged(op, clrtype, out arg, false);
                                    }
                                    // this takes care of implicit conversions
                                    var opImplicit = parameter.ParameterType.GetMethod("op_Implicit", new[] { clrtype });
                                    if (opImplicit != null)
                                    {
                                        usedImplicitConversion = typematch = opImplicit.ReturnType == parameter.ParameterType;
                                        clrtype = parameter.ParameterType;
                                    }
                                }
                                Runtime.XDecref(pyoptype);
                                if (!typematch)
                                {
                                    margs = null;
                                    break;
                                }
                            }
                            else
                            {
                                clrtype = parameter.ParameterType;
                            }
                        }
                        else
                        {
                            clrtype = parameter.ParameterType;
                        }

                        if (parameter.IsOut || clrtype.IsByRef)
                        {
                            outs++;
                        }

                        if (!Converter.ToManaged(op, clrtype, out arg, false))
                        {
                            Exceptions.Clear();
                            margs = null;
                            break;
                        }

                        if (isNewReference)
                        {
                            // TODO: is this a bug? Should this happen even if the conversion fails?
                            // GetSlice() creates a new reference but GetItem()
                            // returns only a borrow reference.
                            Runtime.XDecref(op);
                        }

                        margs[paramIndex] = arg;
                    }

                    if (margs == null)
                    {
                        continue;
                    }

                    if (isOperator)
                    {
                        if (inst != IntPtr.Zero)
                        {
                            if (ManagedType.GetManagedObject(inst) is CLRObject co)
                            {
                                bool isUnary = pyArgCount == 0;
                                // Postprocessing to extend margs.
                                var margsTemp = isUnary ? new object[1] : new object[2];
                                // If reverse, the bound instance is the right operand.
                                int boundOperandIndex = isReverse ? 1 : 0;
                                // If reverse, the passed instance is the left operand.
                                int passedOperandIndex = isReverse ? 0 : 1;
                                margsTemp[boundOperandIndex] = co.inst;
                                if (!isUnary)
                                {
                                    margsTemp[passedOperandIndex] = margs[0];
                                }
                                margs = margsTemp;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }

                    object target = null;
                    if (!mi.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    var binding = new Binding(mi, target, margs, outs);
                    if (usedImplicitConversion)
                    {
                        // lets just keep the first binding using implicit conversion
                        // this is to respect method order/precedence
                        if (bindingUsingImplicitConversion == null)
                        {
                            // in this case we will not return the binding yet in case there is a match
                            // which does not use implicit conversions, which will return directly
                            bindingUsingImplicitConversion = binding;
                        }
                    }
                    else
                    {
                        return(binding);
                    }
                }
            }

            // if we generated a binding using implicit conversion return it
            if (bindingUsingImplicitConversion != null)
            {
                return(bindingUsingImplicitConversion);
            }

            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodinfo != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(args, true);
                MethodInfo mi    = MatchParameters(methodinfo, types);
                return(Bind(inst, args, kw, mi, null));
            }
            return(null);
        }
Пример #9
0
        internal Binding Bind(IntPtr inst, IntPtr pythonParametersPtr, IntPtr kw, MethodBase info, MethodInfo[] methodInfoArray)
        {
            // loop to find match, return invoker w/ or /wo error
            MethodBase[] _methods = null;
            // NOTE: return the size of the args pointer (the number of parameter from the python call)
            int pythonParameterCount = Runtime.PyTuple_Size(pythonParametersPtr);
            //WHY: Why is that so widely scoped ?
            object    pythonManagedParameterPtr;
            var       isGeneric            = false;
            ArrayList defaultParameterList = null;

            if (info != null)
            {
                // NOTE: If a MethodBase object has been provided, create an array with only it.
                // WHY a method base is provided some times and not other ? (ex: when call a genric with a type in [])
                _methods = new MethodBase[1];
                _methods.SetValue(info, 0);
            }
            else
            {
                // NOTE: Create an array of MethodBase from teh called method/constructor
                // WHY not use the methodinfo provided?
                _methods = GetMethods();
            }
            //WHY is it so widely scoped
            Type clrConvertedParameterType;

            // TODO: Clean up
            foreach (MethodBase methodInfo in _methods)
            {
                //WHY not just do isGeneric = mi.IsGenericMethod or use it directly ?
                if (methodInfo.IsGenericMethod)
                {
                    isGeneric = true;
                }
                //NOTE: Get the parameter from the current MethodBase
                //NOTE: MethodInfo Ok
                ParameterInfo[] clrParameterInfoArray = methodInfo.GetParameters();
                //NOTE: Get the number of clr parameters
                int clrParameterCount = clrParameterInfoArray.Length;

                var paramCountMatch = false;
                //REFACTOR: Use var like the other local variables
                var clrHasParamArray    = false;
                var clrParamsArrayStart = -1;

                var byRefCount = 0;

                if (pythonParameterCount == clrParameterCount)
                {
                    paramCountMatch = true;
                }
                else if (pythonParameterCount < clrParameterCount)
                {
                    paramCountMatch      = true;
                    defaultParameterList = new ArrayList();
                    for (int v = pythonParameterCount; v < clrParameterCount; v++)
                    {
                        if (clrParameterInfoArray[v].DefaultValue == DBNull.Value)
                        {
                            paramCountMatch = false;
                        }
                        else
                        {
                            defaultParameterList.Add(clrParameterInfoArray[v].DefaultValue);
                        }
                    }
                }
                else if (pythonParameterCount > clrParameterCount && clrParameterCount > 0 &&
                         Attribute.IsDefined(clrParameterInfoArray[clrParameterCount - 1], typeof(ParamArrayAttribute)))
                {
                    // This is a `foo({...}, params object[] bar)` style method
                    paramCountMatch     = true;
                    clrHasParamArray    = true;
                    clrParamsArrayStart = clrParameterCount - 1;
                }

                if (paramCountMatch)
                {
                    var methodParametersPtrArray = new object[clrParameterCount];

                    for (var n = 0; n < clrParameterCount; n++)
                    {
                        IntPtr pythonParameterPtr;
                        if (n < pythonParameterCount)
                        {
                            if (clrParamsArrayStart == n)
                            {
                                // map remaining Python arguments to a tuple since
                                // the managed function accepts it - hopefully :]
                                //WHY: Hmmm it returns a lot of python paramter as one. isn't there a problem later ?
                                pythonParameterPtr = Runtime.PyTuple_GetSlice(pythonParametersPtr, clrParamsArrayStart, pythonParameterCount);
                            }
                            else
                            {
                                pythonParameterPtr = Runtime.PyTuple_GetItem(pythonParametersPtr, n);
                            }

                            // this logic below handles cases when multiple overloading methods
                            // are ambiguous, hence comparison between Python and CLR types
                            // is necessary
                            clrConvertedParameterType = null;
                            IntPtr pythonParameterPtrType = IntPtr.Zero;
                            if (_methods.Length > 1)
                            {
                                pythonParameterPtrType = Runtime.PyObject_Type(pythonParameterPtr);
                                Exceptions.Clear();
                                if (pythonParameterPtrType != IntPtr.Zero)
                                {
                                    clrConvertedParameterType = Converter.GetTypeByAlias(pythonParameterPtrType);
                                }
                                Runtime.XDecref(pythonParameterPtrType);
                            }


                            if (clrConvertedParameterType != null)
                            {
                                var parameterTypeMatch = false;
                                if ((clrParameterInfoArray[n].ParameterType != typeof(object)) && (clrParameterInfoArray[n].ParameterType != clrConvertedParameterType))
                                {
                                    IntPtr pythonConvertedParameterPtrType = Converter.GetPythonTypeByAlias(clrParameterInfoArray[n].ParameterType);
                                    pythonParameterPtrType = Runtime.PyObject_Type(pythonParameterPtr);
                                    Exceptions.Clear();
                                    if (pythonParameterPtrType != IntPtr.Zero)
                                    {
                                        if (pythonConvertedParameterPtrType != pythonParameterPtrType)
                                        {
                                            parameterTypeMatch = false;
                                        }
                                        else
                                        {
                                            parameterTypeMatch        = true;
                                            clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                                        }
                                    }
                                    if (!parameterTypeMatch)
                                    {
                                        // this takes care of enum values
                                        TypeCode clrParameterTypeCode          = Type.GetTypeCode(clrParameterInfoArray[n].ParameterType);
                                        TypeCode clrConvertedParameterTypeCode = Type.GetTypeCode(clrConvertedParameterType);
                                        if (clrParameterTypeCode == clrConvertedParameterTypeCode)
                                        {
                                            parameterTypeMatch        = true;
                                            clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                                        }
                                    }
                                    Runtime.XDecref(pythonParameterPtrType);
                                    if (!parameterTypeMatch)
                                    {
                                        methodParametersPtrArray = null;
                                        break;
                                    }
                                }
                                else
                                {
                                    parameterTypeMatch        = true;
                                    clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                                }
                            }
                            else
                            {
                                clrConvertedParameterType = clrParameterInfoArray[n].ParameterType;
                            }

                            if (clrParameterInfoArray[n].IsOut || clrConvertedParameterType.IsByRef)
                            {
                                byRefCount++;
                            }

                            if (!Converter.ToManaged(pythonParameterPtr, clrConvertedParameterType, out pythonManagedParameterPtr, false))
                            {
                                Exceptions.Clear();
                                methodParametersPtrArray = null;
                                break;
                            }
                            if (clrParamsArrayStart == n)
                            {
                                // GetSlice() creates a new reference but GetItem()
                                // returns only a borrow reference.
                                Runtime.XDecref(pythonParameterPtr);
                            }
                            methodParametersPtrArray[n] = pythonParameterPtr;
                        }
                        else
                        {
                            if (defaultParameterList != null)
                            {
                                methodParametersPtrArray[n] = defaultParameterList[n - pythonParameterCount];
                            }
                        }
                    }

                    if (methodParametersPtrArray == null)
                    {
                        continue;
                    }

                    object target = null;
                    if (!methodInfo.IsStatic && inst != IntPtr.Zero)
                    {
                        //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
                        // InvalidCastException: Unable to cast object of type
                        // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
                        var co = ManagedType.GetManagedObject(inst) as CLRObject;

                        // Sanity check: this ensures a graceful exit if someone does
                        // something intentionally wrong like call a non-static method
                        // on the class rather than on an instance of the class.
                        // XXX maybe better to do this before all the other rigmarole.
                        if (co == null)
                        {
                            return(null);
                        }
                        target = co.inst;
                    }

                    return(new Binding(methodInfo, target, methodParametersPtrArray, byRefCount));
                }
            }
            // We weren't able to find a matching method but at least one
            // is a generic method and info is null. That happens when a generic
            // method was not called using the [] syntax. Let's introspect the
            // type of the arguments and use it to construct the correct method.
            if (isGeneric && info == null && methodInfoArray != null)
            {
                Type[]     types = Runtime.PythonArgsToTypeArray(pythonParametersPtr, true);
                MethodInfo mi    = MatchParameters(methodInfoArray, types);
                return(Bind(inst, pythonParametersPtr, kw, mi, null));
            }
            return(null);
        }
Пример #10
0
        /// <summary>
        /// Implements __contains__ for dictionary types.
        /// </summary>
        public static int sq_contains(BorrowedReference ob, BorrowedReference v)
        {
            var obj  = (CLRObject)GetManagedObject(ob);
            var self = obj.inst;

            var key        = Tuple.Create(self.GetType(), "ContainsKey");
            var methodInfo = methodsByType[key];

            var    parameters = methodInfo.GetParameters();
            object arg;

            if (!Converter.ToManaged(v, parameters[0].ParameterType, out arg, false))
            {
                Exceptions.SetError(Exceptions.TypeError,
                                    $"invalid parameter type for sq_contains: should be {Converter.GetTypeByAlias(v)}, found {parameters[0].ParameterType}");
            }

            return((bool)methodInfo.Invoke(self, new[] { arg }) ? 1 : 0);
        }
Пример #11
0
        internal static MethodInfo MatchByTypeSig(MethodInfo[] msig,
                                                  IntPtr psig)
        {
            IntPtr args = psig;
            bool   free = false;

            if (!Runtime.PyTuple_Check(psig))
            {
                args = Runtime.PyTuple_New(1);
                Runtime.Incref(psig);
                Runtime.PyTuple_SetItem(args, 0, psig);
                free = true;
            }

            int        plen  = Runtime.PyTuple_Size(args);
            MethodInfo match = null;

            // XXX: what about out args, etc.?

            for (int i = 0; i < msig.Length; i++)
            {
                ParameterInfo[] pi = msig[i].GetParameters();
                if (pi.Length != plen)
                {
                    continue;
                }
                bool matched = true;
                for (int n = 0; n < pi.Length; n++)
                {
                    IntPtr p = Runtime.PyTuple_GetItem(args, n);
                    if (p == IntPtr.Zero)
                    {
                        Exceptions.Clear();
                        break;
                    }
                    ClassBase c = ManagedType.GetManagedObject(p) as ClassBase;
                    Type      t = (c != null) ? c.type :
                                  Converter.GetTypeByAlias(p);

                    if (t == null)
                    {
                        break;
                    }
                    if (t != pi[n].ParameterType)
                    {
                        matched = false;
                        break;
                    }
                }
                if (matched)
                {
                    match = msig[i];
                    break;
                }
            }

            if (free)
            {
                Runtime.Decref(args);
            }

            return(match);
        }