/// <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); } }
/// <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)); }
/// <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); }
/// <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); }
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)); }
/// <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); }
/// <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); }
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); }
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); }
/// <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); }
/// <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); } }
public override bool TryConvert(ConvertBinder binder, out object result) { return(Converter.ToManaged(this.obj, binder.Type, out result, false)); }