Exemple #1
0
        /// <summary>
        /// Descriptor __set__ implementation. This method sets the value of
        /// a field based on the given Python value. The Python value must be
        /// convertible to the type of the field.
        /// </summary>
        public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
        {
            var    self = (FieldObject)GetManagedObject(ds);
            object newval;

            if (self == null)
            {
                return(-1);
            }

            if (val == IntPtr.Zero)
            {
                Exceptions.SetError(Exceptions.TypeError, "cannot delete field");
                return(-1);
            }

            FieldInfo info = self.info;

            if (info.IsLiteral || info.IsInitOnly)
            {
                Exceptions.SetError(Exceptions.TypeError, "field is read-only");
                return(-1);
            }

            bool is_static = info.IsStatic;

            if (ob == IntPtr.Zero || ob == Runtime.PyNone)
            {
                if (!is_static)
                {
                    Exceptions.SetError(Exceptions.TypeError, "instance attribute must be set through a class instance");
                    return(-1);
                }
            }

            if (!Converter.ToManaged(val, info.FieldType, out newval, true))
            {
                return(-1);
            }

            try
            {
                if (!is_static)
                {
                    var co = (CLRObject)GetManagedObject(ob);
                    info.SetValue(co.inst, newval);
                }
                else
                {
                    info.SetValue(null, newval);
                }
                return(0);
            }
            catch (Exception e)
            {
                Exceptions.SetError(Exceptions.TypeError, e.Message);
                return(-1);
            }
        }
Exemple #2
0
        /// <summary>
        /// Implements __new__ for reflected classes and value types.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = GetManagedObject(tp) as ClassObject;

            // Sanity check: this ensures a graceful error if someone does
            // something intentially wrong like use the managed metatype for
            // a class that is not really derived from a managed class.
            if (self == null)
            {
                return(Exceptions.RaiseTypeError("invalid object"));
            }

            Type type = self.type;

            // Primitive types do not have constructors, but they look like
            // they do from Python. If the ClassObject represents one of the
            // convertible primitive types, just convert the arg directly.
            if (type.IsPrimitive || type == typeof(string))
            {
                if (Runtime.PyTuple_Size(args) != 1)
                {
                    Exceptions.SetError(Exceptions.TypeError, "no constructors match given arguments");
                    return(IntPtr.Zero);
                }

                IntPtr op = Runtime.PyTuple_GetItem(args, 0);
                object result;

                if (!Converter.ToManaged(op, type, out result, true))
                {
                    return(IntPtr.Zero);
                }

                return(CLRObject.GetInstHandle(result, tp));
            }

            if (type.IsAbstract)
            {
                Exceptions.SetError(Exceptions.TypeError, "cannot instantiate abstract class");
                return(IntPtr.Zero);
            }

            if (type.IsEnum)
            {
                Exceptions.SetError(Exceptions.TypeError, "cannot instantiate enumeration");
                return(IntPtr.Zero);
            }

            object obj = self.binder.InvokeRaw(IntPtr.Zero, args, kw);

            if (obj == null)
            {
                return(IntPtr.Zero);
            }

            return(CLRObject.GetInstHandle(obj, tp));
        }
Exemple #3
0
        /// <summary>
        /// AsManagedObject Method
        /// </summary>
        /// <remarks>
        /// Return a managed object of the given type, based on the
        /// value of the Python object.
        /// </remarks>
        public object AsManagedObject(Type t)
        {
            object result;

            if (!Converter.ToManaged(obj, t, out result, false))
            {
                throw new InvalidCastException("cannot convert object to target type");
            }
            return(result);
        }
Exemple #4
0
        /// <summary>
        /// As Method
        /// </summary>
        /// <remarks>
        /// Return a managed object of the given type, based on the
        /// value of the Python object.
        /// </remarks>
        public T As <T>()
        {
            if (typeof(T) == typeof(PyObject) || typeof(T) == typeof(object))
            {
                return((T)(this as object));
            }
            object result;

            if (!Converter.ToManaged(obj, typeof(T), out result, false))
            {
                throw new InvalidCastException("cannot convert object to target type");
            }
            return((T)result);
        }
Exemple #5
0
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = GetManagedObject(tp) as ArrayObject;

            if (Runtime.PyTuple_Size(args) != 1)
            {
                return(Exceptions.RaiseTypeError("array expects 1 argument"));
            }
            IntPtr op = Runtime.PyTuple_GetItem(args, 0);
            object result;

            if (!Converter.ToManaged(op, self.type, out result, true))
            {
                return(IntPtr.Zero);
            }
            return(CLRObject.GetInstHandle(result, tp));
        }
Exemple #6
0
        /// <summary>
        /// Convert a Python value to a correctly typed managed array instance.
        /// The Python value must support the Python sequence protocol and the
        /// items in the sequence must be convertible to the target array type.
        /// </summary>
        private static bool ToArray(IntPtr value, Type obType, out object result, bool setError)
        {
            Type elementType = obType.GetElementType();
            var  size        = Runtime.PySequence_Size(value);

            result = null;

            if (size < 0)
            {
                if (setError)
                {
                    SetConversionError(value, obType);
                }
                return(false);
            }

            Array items = Array.CreateInstance(elementType, size);

            // XXX - is there a better way to unwrap this if it is a real array?
            for (var i = 0; i < size; i++)
            {
                object obj  = null;
                IntPtr item = Runtime.PySequence_GetItem(value, i);
                if (item == IntPtr.Zero)
                {
                    if (setError)
                    {
                        SetConversionError(value, obType);
                        return(false);
                    }
                }

                if (!Converter.ToManaged(item, elementType, out obj, true))
                {
                    Runtime.XDecref(item);
                    return(false);
                }

                items.SetValue(obj, i);
                Runtime.XDecref(item);
            }

            result = items;
            return(true);
        }
Exemple #7
0
        /// <summary>
        /// Implements __contains__ for array types.
        /// </summary>
        public static int sq_contains(IntPtr ob, IntPtr v)
        {
            var    obj      = (CLRObject)GetManagedObject(ob);
            Type   itemType = obj.inst.GetType().GetElementType();
            var    items    = obj.inst as IList;
            object value;

            if (!Converter.ToManaged(v, itemType, out value, false))
            {
                return(0);
            }

            if (items.Contains(value))
            {
                return(1);
            }

            return(0);
        }
Exemple #8
0
        public object TrueDispatch(ArrayList args)
        {
            MethodInfo method = dtype.GetMethod("Invoke");

            ParameterInfo[] pi     = method.GetParameters();
            IntPtr          pyargs = Runtime.PyTuple_New(pi.Length);
            Type            rtype  = method.ReturnType;

            for (var i = 0; i < pi.Length; i++)
            {
                // Here we own the reference to the Python value, and we
                // give the ownership to the arg tuple.
                IntPtr arg = Converter.ToPython(args[i], pi[i].ParameterType);
                Runtime.PyTuple_SetItem(pyargs, i, arg);
            }

            IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero);

            Runtime.XDecref(pyargs);

            if (op == IntPtr.Zero)
            {
                var e = new PythonException();
                throw e;
            }

            if (rtype == typeof(void))
            {
                return(null);
            }

            object result = null;

            if (!Converter.ToManaged(op, rtype, out result, false))
            {
                Runtime.XDecref(op);
                throw new ConversionException($"could not convert Python result to {rtype}");
            }

            Runtime.XDecref(op);
            return(result);
        }
Exemple #9
0
        static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution,
                                       out object arg, out bool isOut)
        {
            arg   = null;
            isOut = false;
            var clrtype = TryComputeClrArgumentType(parameterType, op, needsResolution: needsResolution);

            if (clrtype == null)
            {
                return(false);
            }

            if (!Converter.ToManaged(op, clrtype, out arg, false))
            {
                Exceptions.Clear();
                return(false);
            }

            isOut = clrtype.IsByRef;
            return(true);
        }
Exemple #10
0
        /// <summary>
        /// Implements __setitem__ for array types.
        /// </summary>
        public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
        {
            var    obj      = (CLRObject)GetManagedObject(ob);
            var    items    = obj.inst as Array;
            Type   itemType = obj.inst.GetType().GetElementType();
            int    rank     = items.Rank;
            int    index;
            object value;

            if (items.IsReadOnly)
            {
                Exceptions.RaiseTypeError("array is read-only");
                return(-1);
            }

            if (!Converter.ToManaged(v, itemType, out value, true))
            {
                return(-1);
            }

            if (rank == 1)
            {
                index = Runtime.PyInt_AsLong(idx);

                if (Exceptions.ErrorOccurred())
                {
                    Exceptions.RaiseTypeError("invalid index value");
                    return(-1);
                }

                if (index < 0)
                {
                    index = items.Length + index;
                }

                try {
                    items.SetValue(value, index);
                }
                catch (IndexOutOfRangeException) {
                    Exceptions.SetError(Exceptions.IndexError, "array index out of range");
                    return(-1);
                }

                return(0);
            }

            if (!Runtime.PyTuple_Check(idx))
            {
                Exceptions.RaiseTypeError("invalid index value");
                return(-1);
            }

            var count = Runtime.PyTuple_Size(idx);
            var args  = new int[count];

            for (var i = 0; i < count; i++)
            {
                IntPtr op = Runtime.PyTuple_GetItem(idx, i);
                index = Runtime.PyInt_AsLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Exceptions.RaiseTypeError("invalid index value");
                    return(-1);
                }

                if (index < 0)
                {
                    index = items.GetLength(i) + index;
                }

                args.SetValue(index, i);
            }

            try {
                items.SetValue(value, args);
            }
            catch (IndexOutOfRangeException) {
                Exceptions.SetError(Exceptions.IndexError, "array index out of range");
                return(-1);
            }

            return(0);
        }
Exemple #11
0
        /// <summary>
        /// Descriptor __set__ implementation. This method sets the value of
        /// a property based on the given Python value. The Python value must
        /// be convertible to the type of the property.
        /// </summary>
        public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
        {
            var        self   = (PropertyObject)GetManagedObject(ds);
            MethodInfo setter = self.setter;
            object     newval;

            if (val == IntPtr.Zero)
            {
                Exceptions.RaiseTypeError("cannot delete property");
                return(-1);
            }

            if (setter == null)
            {
                Exceptions.RaiseTypeError("property is read-only");
                return(-1);
            }


            if (!Converter.ToManaged(val, self.info.PropertyType, out newval, true))
            {
                return(-1);
            }

            bool is_static = setter.IsStatic;

            if (ob == IntPtr.Zero || ob == Runtime.PyNone)
            {
                if (!is_static)
                {
                    Exceptions.RaiseTypeError("instance property must be set on an instance");
                    return(-1);
                }
            }

            try {
                if (!is_static)
                {
                    var co = GetManagedObject(ob) as CLRObject;
                    if (co == null)
                    {
                        Exceptions.RaiseTypeError("invalid target");
                        return(-1);
                    }
                    self.info.SetValue(co.inst, newval, null);
                }
                else
                {
                    self.info.SetValue(null, newval, null);
                }
                return(0);
            }
            catch (Exception e) {
                if (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                Exceptions.SetError(e);
                return(-1);
            }
        }
Exemple #12
0
 public override bool TryConvert(ConvertBinder binder, out object result)
 {
     return(Converter.ToManaged(this.obj, binder.Type, out result, false));
 }