Esempio n. 1
0
        internal static IntPtr GetInstHandle(object ob, Type type)
        {
            ClassBase cc = ClassManager.GetClass(type);
            CLRObject co = GetInstance(ob, cc.tpHandle);

            return(co.pyHandle);
        }
Esempio n. 2
0
        public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, object[] args)
        {
            // call the base constructor
            obj.GetType().InvokeMember(origCtorName,
                                       BindingFlags.InvokeMethod,
                                       null,
                                       obj,
                                       args);

            CLRObject self = null;
            IntPtr    gs   = Runtime.PyGILState_Ensure();

            try {
                // create the python object
                IntPtr type = TypeManager.GetTypeHandle(obj.GetType());
                self = new CLRObject(obj, type);

                // set __pyobj__ to self and deref the python object which will allow this
                // object to be collected.
                FieldInfo fi = obj.GetType().GetField("__pyobj__");
                fi.SetValue(obj, self);
            }
            finally {
                // Decrement the python object's reference count.
                // This doesn't actually destroy the object, it just sets the reference to this object
                // to be a weak reference and it will be destroyed when the C# object is destroyed.
                if (null != self)
                {
                    Runtime.XDecref(self.pyHandle);
                }

                Runtime.PyGILState_Release(gs);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// SetError Method
        /// </summary>
        /// <remarks>
        /// Sets the current Python exception given a CLR exception
        /// object. The CLR exception instance is wrapped as a Python
        /// object, allowing it to be handled naturally from Python.
        /// </remarks>
        public static void SetError(Exception e)
        {
            // Because delegates allow arbitrary nesting of Python calling
            // managed calling Python calling... etc. it is possible that we
            // might get a managed exception raised that is a wrapper for a
            // Python exception. In that case we'd rather have the real thing.

            var pe = e as PythonException;

            if (pe != null)
            {
                Runtime.XIncref(pe.PyType);
                Runtime.XIncref(pe.PyValue);
                Runtime.XIncref(pe.PyTB);
                Runtime.PyErr_Restore(pe.PyType, pe.PyValue, pe.PyTB);
                return;
            }

            IntPtr op    = CLRObject.GetInstHandle(e);
            IntPtr etype = Runtime.PyObject_GetAttrString(op, "__class__");

            Runtime.PyErr_SetObject(etype, op);
            Runtime.XDecref(etype);
            Runtime.XDecref(op);
        }
Esempio n. 4
0
        /// <summary>
        /// Set the 'args' slot on a python exception object that wraps
        /// a CLR exception. This is needed for pickling CLR exceptions as
        /// BaseException_reduce will only check the slots, bypassing the
        /// __getattr__ implementation, and thus dereferencing a NULL
        /// pointer.
        /// </summary>
        /// <param name="ob">The python object wrapping </param>
        internal static void SetArgsAndCause(IntPtr ob)
        {
            // e: A CLR Exception
            Exception e = ExceptionClassObject.ToException(ob);

            if (e == null)
            {
                return;
            }

            IntPtr args;

            if (!string.IsNullOrEmpty(e.Message))
            {
                args = Runtime.PyTuple_New(1);
                IntPtr msg = Runtime.PyUnicode_FromString(e.Message);
                Runtime.PyTuple_SetItem(args, 0, msg);
            }
            else
            {
                args = Runtime.PyTuple_New(0);
            }

            Marshal.WriteIntPtr(ob, ExceptionOffset.args, args);

#if PYTHON3
            if (e.InnerException != null)
            {
                IntPtr cause = CLRObject.GetInstHandle(e.InnerException);
                Marshal.WriteIntPtr(ob, ExceptionOffset.cause, cause);
            }
#endif
        }
Esempio n. 5
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));
        }
Esempio n. 6
0
        /// <summary>
        /// FromManagedObject Method
        /// </summary>
        /// <remarks>
        /// Given an arbitrary managed object, return a Python instance that
        /// reflects the managed object.
        /// </remarks>
        public static PyObject FromManagedObject(object ob)
        {
            // Special case: if ob is null, we return None.
            if (ob == null)
            {
                Runtime.XIncref(Runtime.PyNone);
                return(new PyObject(Runtime.PyNone));
            }
            IntPtr op = CLRObject.GetInstHandle(ob);

            return(new PyObject(op));
        }
Esempio n. 7
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));
        }
Esempio n. 8
0
        /// <summary>
        /// DelegateObject __new__ implementation. The result of this is a new
        /// PyObject whose type is DelegateObject and whose ob_data is a handle
        /// to an actual delegate instance. The method wrapped by the actual
        /// delegate instance belongs to an object generated to relay the call
        /// to the Python callable passed in.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var self = (DelegateObject)GetManagedObject(tp);

            if (Runtime.PyTuple_Size(args) != 1)
            {
                return(Exceptions.RaiseTypeError("class takes exactly one argument"));
            }

            IntPtr method = Runtime.PyTuple_GetItem(args, 0);

            if (Runtime.PyCallable_Check(method) != 1)
            {
                return(Exceptions.RaiseTypeError("argument must be callable"));
            }

            Delegate d = PythonEngine.DelegateManager.GetDelegate(self.type, method);

            return(CLRObject.GetInstHandle(d, self.pyHandle));
        }
Esempio n. 9
0
        /// <summary>
        /// Implements __new__ for reflected interface types.
        /// </summary>
        public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
        {
            var    self  = (InterfaceObject)GetManagedObject(tp);
            var    nargs = Runtime.PyTuple_Size(args);
            Type   type  = self.type;
            object obj;

            if (nargs == 1)
            {
                IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
                var    co   = GetManagedObject(inst) as CLRObject;

                if (co == null || !type.IsInstanceOfType(co.inst))
                {
                    Exceptions.SetError(Exceptions.TypeError, $"object does not implement {type.Name}");
                    return(IntPtr.Zero);
                }

                obj = co.inst;
            }

            else if (nargs == 0 && self.ctor != null)
            {
                obj = self.ctor.Invoke(null);

                if (obj == null || !type.IsInstanceOfType(obj))
                {
                    Exceptions.SetError(Exceptions.TypeError, "CoClass default constructor failed");
                    return(IntPtr.Zero);
                }
            }

            else
            {
                Exceptions.SetError(Exceptions.TypeError, "interface takes exactly one argument");
                return(IntPtr.Zero);
            }

            return(CLRObject.GetInstHandle(obj, self.pyHandle));
        }
Esempio n. 10
0
        /// <summary>
        /// BoundContructor.__call__(PyObject *callable_object, PyObject *args, PyObject *kw)
        /// </summary>
        /// <param name="op"> PyObject *callable_object </param>
        /// <param name="args"> PyObject *args </param>
        /// <param name="kw"> PyObject *kw </param>
        /// <returns> A reference to a new instance of the class by invoking the selected ctor(). </returns>
        public static IntPtr tp_call(IntPtr op, IntPtr args, IntPtr kw)
        {
            var self = (BoundContructor)GetManagedObject(op);
            // Even though a call with null ctorInfo just produces the old behavior

            /*if (self.ctorInfo == null) {
             *  string msg = "Usage: Class.Overloads[CLR_or_python_Type, ...]";
             *  return Exceptions.RaiseTypeError(msg);
             * }*/
            // Bind using ConstructorBinder.Bind and invoke the ctor providing a null instancePtr
            // which will fire self.ctorInfo using ConstructorInfo.Invoke().
            object obj = self.ctorBinder.InvokeRaw(IntPtr.Zero, args, kw, self.ctorInfo);

            if (obj == null)
            {
                // XXX set an error
                return(IntPtr.Zero);
            }
            // Instantiate the python object that wraps the result of the method call
            // and return the PyObject* to it.
            return(CLRObject.GetInstHandle(obj, self.pyTypeHndl));
        }
Esempio n. 11
0
        internal static IntPtr GetInstHandle(object ob)
        {
            CLRObject co = GetInstance(ob);

            return(co.pyHandle);
        }
Esempio n. 12
0
        internal static IntPtr ToPython(object value, Type type)
        {
            if (value is PyObject)
            {
                IntPtr handle = ((PyObject)value).Handle;
                Runtime.XIncref(handle);
                return(handle);
            }
            IntPtr result = IntPtr.Zero;

            // Null always converts to None in Python.

            if (value == null)
            {
                result = Runtime.PyNone;
                Runtime.XIncref(result);
                return(result);
            }

            if (value is IList && !(value is INotifyPropertyChanged) && value.GetType().IsGenericType)
            {
                using (var resultlist = new PyList())
                {
                    foreach (object o in (IEnumerable)value)
                    {
                        using (var p = new PyObject(ToPython(o, o?.GetType())))
                        {
                            resultlist.Append(p);
                        }
                    }
                    Runtime.XIncref(resultlist.Handle);
                    return(resultlist.Handle);
                }
            }

            // it the type is a python subclass of a managed type then return the
            // underlying python object rather than construct a new wrapper object.
            var pyderived = value as IPythonDerivedType;

            if (null != pyderived)
            {
                #if NETSTANDARD
                return(ClassDerivedObject.ToPython(pyderived));
                #else
                // if object is remote don't do this
                if (!System.Runtime.Remoting.RemotingServices.IsTransparentProxy(pyderived))
                {
                    return(ClassDerivedObject.ToPython(pyderived));
                }
                #endif
            }

            // hmm - from Python, we almost never care what the declared
            // type is. we'd rather have the object bound to the actual
            // implementing class.

            type = value.GetType();

            TypeCode tc = Type.GetTypeCode(type);

            switch (tc)
            {
            case TypeCode.Object:
                return(CLRObject.GetInstHandle(value, type));

            case TypeCode.String:
                return(Runtime.PyUnicode_FromString((string)value));

            case TypeCode.Int32:
                return(Runtime.PyInt_FromInt32((int)value));

            case TypeCode.Boolean:
                if ((bool)value)
                {
                    Runtime.XIncref(Runtime.PyTrue);
                    return(Runtime.PyTrue);
                }
                Runtime.XIncref(Runtime.PyFalse);
                return(Runtime.PyFalse);

            case TypeCode.Byte:
                return(Runtime.PyInt_FromInt32((int)((byte)value)));

            case TypeCode.Char:
                return(Runtime.PyUnicode_FromOrdinal((int)((char)value)));

            case TypeCode.Int16:
                return(Runtime.PyInt_FromInt32((int)((short)value)));

            case TypeCode.Int64:
                return(Runtime.PyLong_FromLongLong((long)value));

            case TypeCode.Single:
                // return Runtime.PyFloat_FromDouble((double)((float)value));
                string ss = ((float)value).ToString(nfi);
                IntPtr ps = Runtime.PyString_FromString(ss);
                IntPtr op = Runtime.PyFloat_FromString(ps, IntPtr.Zero);
                Runtime.XDecref(ps);
                return(op);

            case TypeCode.Double:
                return(Runtime.PyFloat_FromDouble((double)value));

            case TypeCode.SByte:
                return(Runtime.PyInt_FromInt32((int)((sbyte)value)));

            case TypeCode.UInt16:
                return(Runtime.PyInt_FromInt32((int)((ushort)value)));

            case TypeCode.UInt32:
                return(Runtime.PyLong_FromUnsignedLong((uint)value));

            case TypeCode.UInt64:
                return(Runtime.PyLong_FromUnsignedLongLong((ulong)value));

            default:
                if (value is IEnumerable)
                {
                    using (var resultlist = new PyList())
                    {
                        foreach (object o in (IEnumerable)value)
                        {
                            using (var p = new PyObject(ToPython(o, o?.GetType())))
                            {
                                resultlist.Append(p);
                            }
                        }
                        Runtime.XIncref(resultlist.Handle);
                        return(resultlist.Handle);
                    }
                }
                result = CLRObject.GetInstHandle(value, type);
                return(result);
            }
        }