Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
0
        public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName,
                                            object[] args)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            if (null != self)
            {
                var    disposeList = new List <PyObject>();
                IntPtr gs          = Runtime.PyGILState_Ensure();
                try {
                    Runtime.XIncref(self.pyHandle);
                    var pyself = new PyObject(self.pyHandle);
                    disposeList.Add(pyself);

                    Runtime.XIncref(Runtime.PyNone);
                    var pynone = new PyObject(Runtime.PyNone);
                    disposeList.Add(pynone);

                    PyObject method = pyself.GetAttr(methodName, pynone);
                    disposeList.Add(method);
                    if (method.Handle != Runtime.PyNone)
                    {
                        // if the method hasn't been overridden then it will be a managed object
                        ManagedType managedMethod = ManagedType.GetManagedObject(method.Handle);
                        if (null == managedMethod)
                        {
                            var pyargs = new PyObject[args.Length];
                            for (var i = 0; i < args.Length; ++i)
                            {
                                pyargs[i] = new PyObject(Converter.ToPythonImplicit(args[i]));
                                disposeList.Add(pyargs[i]);
                            }

                            PyObject py_result = method.Invoke(pyargs);
                            disposeList.Add(py_result);
                            return;
                        }
                    }
                }
                finally {
                    foreach (PyObject x in disposeList)
                    {
                        x?.Dispose();
                    }
                    Runtime.PyGILState_Release(gs);
                }
            }

            if (origMethodName == null)
            {
                throw new NotImplementedException($"Python object does not have a '{methodName}' method");
            }

            obj.GetType().InvokeMember(origMethodName,
                                       BindingFlags.InvokeMethod,
                                       null,
                                       obj,
                                       args);
        }
Ejemplo n.º 3
0
        public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName, Object[] args)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            CLRObject self = (CLRObject)fi.GetValue(obj);

            if (null != self)
            {
                List <PyObject> disposeList = new List <PyObject>();
                IntPtr          gs          = Runtime.PyGILState_Ensure();
                try
                {
                    Runtime.Incref(self.pyHandle);
                    PyObject pyself = new PyObject(self.pyHandle);
                    disposeList.Add(pyself);

                    Runtime.Incref(Runtime.PyNone);
                    PyObject pynone = new PyObject(Runtime.PyNone);
                    disposeList.Add(pynone);

                    PyObject method = pyself.GetAttr(methodName, pynone);
                    disposeList.Add(method);
                    if (method.Handle != Runtime.PyNone)
                    {
                        // if the method hasn't been overriden then it will be a managed object
                        ManagedType managedMethod = ManagedType.GetManagedObject(method.Handle);
                        if (null == managedMethod)
                        {
                            PyObject[] pyargs = new PyObject[args.Length];
                            for (int i = 0; i < args.Length; ++i)
                            {
                                pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i].GetType()));
                                disposeList.Add(pyargs[i]);
                            }

                            PyObject py_result = method.Invoke(pyargs);
                            disposeList.Add(py_result);
                            return;
                        }
                    }
                }
                finally
                {
                    foreach (PyObject x in disposeList)
                    {
                        if (x != null)
                        {
                            x.Dispose();
                        }
                    }
                    Runtime.PyGILState_Release(gs);
                }
            }

            obj.GetType().InvokeMember(origMethodName,
                                       BindingFlags.InvokeMethod,
                                       null,
                                       obj,
                                       args);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Called from Converter.ToPython for types that are python subclasses of managed types.
        /// The referenced python object is returned instead of a new wrapper.
        /// </summary>
        internal static IntPtr ToPython(IPythonDerivedType obj)
        {
            // derived types have a __pyobj__ field that gets set to the python
            // object in the overridden constructor
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            Runtime.XIncref(self.pyHandle);

            // when the C# constructor creates the python object it starts as a weak
            // reference with a reference count of 0. Now we're passing this object
            // to Python the reference count needs to be incremented and the reference
            // needs to be replaced with a strong reference to stop the C# object being
            // collected while Python still has a reference to it.
            if (Runtime.Refcount(self.pyHandle) == 1)
            {
                Runtime._Py_NewReference(self.ObjectReference);
                GCHandle gc = GCHandle.Alloc(self, GCHandleType.Normal);
                SetGCHandle(self.ObjectReference, self.TypeReference, gc);
                self.gcHandle.Free();
                self.gcHandle = gc;

                // now the object has a python reference it's safe for the python GC to track it
                Runtime.PyObject_GC_Track(self.pyHandle);
            }

            return(self.pyHandle);
        }
Ejemplo n.º 5
0
        public static void InvokeSetProperty <T>(IPythonDerivedType obj, string propertyName, T value)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            if (null == self)
            {
                throw new NullReferenceException("Instance must be specified when setting a property");
            }

            IntPtr gs = Runtime.PyGILState_Ensure();

            try
            {
                Runtime.XIncref(self.pyHandle);
                using (var pyself = new PyObject(self.pyHandle))
                    using (var pyvalue = new PyObject(Converter.ToPythonImplicit(value)))
                    {
                        pyself.SetAttr(propertyName, pyvalue);
                    }
            }
            finally
            {
                Runtime.PyGILState_Release(gs);
            }
        }
Ejemplo n.º 6
0
        public static T InvokeGetProperty <T>(IPythonDerivedType obj, string propertyName)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            if (null == self)
            {
                throw new NullReferenceException("Instance must be specified when getting a property");
            }

            IntPtr gs = Runtime.PyGILState_Ensure();

            try
            {
                Runtime.XIncref(self.pyHandle);
                using (var pyself = new PyObject(self.pyHandle))
                    using (PyObject pyvalue = pyself.GetAttr(propertyName))
                    {
                        return((T)pyvalue.AsManagedObject(typeof(T)));
                    }
            }
            finally
            {
                Runtime.PyGILState_Release(gs);
            }
        }
Ejemplo n.º 7
0
        public static void Finalize(IPythonDerivedType obj)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            CLRObject self = (CLRObject)fi.GetValue(obj);

            // delete the python object in an asnyc task as we may not be able to acquire
            // the GIL immediately and we don't want to block the GC thread.
            var t = Task.Factory.StartNew(() =>
            {
                // If python's been terminated then there's nothing to do
                if (0 == Runtime.Py_IsInitialized())
                {
                    return;
                }

                IntPtr gs = Runtime.PyGILState_Ensure();
                try
                {
                    // the C# object is being destroyed which must mean there are no more
                    // references to the Python object as well so now we can dealloc the
                    // python object.
                    IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.DictOffset(self.pyHandle));
                    if (dict != IntPtr.Zero)
                    {
                        Runtime.Decref(dict);
                    }
                    Runtime.PyObject_GC_Del(self.pyHandle);
                    self.gcHandle.Free();
                }
                finally
                {
                    Runtime.PyGILState_Release(gs);
                }
            });
        }
Ejemplo n.º 8
0
        public static void Finalize(IPythonDerivedType obj)
        {
            FieldInfo fi   = obj.GetType().GetField("__pyobj__");
            var       self = (CLRObject)fi.GetValue(obj);

            // If python's been terminated then just free the gchandle.
            lock (Runtime.IsFinalizingLock)
            {
                if (0 == Runtime.Py_IsInitialized() || Runtime.IsFinalizing)
                {
                    if (self.gcHandle.IsAllocated)
                    {
                        self.gcHandle.Free();
                    }
                    return;
                }
            }

            // delete the python object in an async task as we may not be able to acquire
            // the GIL immediately and we don't want to block the GC thread.
            // FIXME: t isn't used
            Task t = Task.Factory.StartNew(() =>
            {
                lock (Runtime.IsFinalizingLock)
                {
                    // If python's been terminated then just free the gchandle.
                    if (0 == Runtime.Py_IsInitialized() || Runtime.IsFinalizing)
                    {
                        if (self.gcHandle.IsAllocated)
                        {
                            self.gcHandle.Free();
                        }
                        return;
                    }

                    IntPtr gs = Runtime.PyGILState_Ensure();
                    try
                    {
                        // the C# object is being destroyed which must mean there are no more
                        // references to the Python object as well so now we can dealloc the
                        // python object.
                        Runtime.PyObject_GC_Del(self.pyHandle);
                        self.gcHandle.Free();
                    }
                    finally
                    {
                        Runtime.PyGILState_Release(gs);
                    }
                }
            });
        }
Ejemplo n.º 9
0
        public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, Object[] args)
        {
            // call the base constructor
            obj.GetType().InvokeMember(origCtorName,
                                       BindingFlags.InvokeMethod,
                                       null,
                                       obj,
                                       args);

            List <PyObject> disposeList = new List <PyObject>();
            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);

                Runtime.Incref(self.pyHandle);
                PyObject pyself = new PyObject(self.pyHandle);
                disposeList.Add(pyself);

                Runtime.Incref(Runtime.PyNone);
                PyObject pynone = new PyObject(Runtime.PyNone);
                disposeList.Add(pynone);

                // call __init__
                PyObject init = pyself.GetAttr("__init__", pynone);
                disposeList.Add(init);
                if (init.Handle != Runtime.PyNone)
                {
                    // if __init__ hasn't been overriden then it will be a managed object
                    ManagedType managedMethod = ManagedType.GetManagedObject(init.Handle);
                    if (null == managedMethod)
                    {
                        PyObject[] pyargs = new PyObject[args.Length];
                        for (int i = 0; i < args.Length; ++i)
                        {
                            pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i].GetType()));
                            disposeList.Add(pyargs[i]);
                        }

                        disposeList.Add(init.Invoke(pyargs));
                    }
                }
            }
            finally
            {
                foreach (PyObject x in disposeList)
                {
                    if (x != null)
                    {
                        x.Dispose();
                    }
                }

                // 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.Decref(self.pyHandle);
                }

                Runtime.PyGILState_Release(gs);
            }
        }