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); } }
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); } }); }
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); } }
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); }
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); } } }); }
public static void DomainReloadAndGC() { Assert.IsFalse(PythonEngine.IsInitialized); RunAssemblyAndUnload("test1"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); RunAssemblyAndUnload("test2"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); if (PythonEngine.DefaultShutdownMode == ShutdownMode.Normal) { // The default mode is a normal mode, // it should shutdown the Python VM avoiding influence other tests. PyRuntime.PyGILState_Ensure(); PyRuntime.Py_Finalize(); } }
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 BorrowedReference type = TypeManager.GetTypeReference(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); } }
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); }
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); } }
/// <summary> /// AcquireLock Method /// </summary> /// /// <remarks> /// Acquire the Python global interpreter lock (GIL). Managed code /// *must* call this method before using any objects or calling any /// methods on objects in the Python.Runtime namespace. The only /// exception is PythonEngine.Initialize, which may be called without /// first calling AcquireLock. /// /// Each call to AcquireLock must be matched by a corresponding call /// to ReleaseLock, passing the token obtained from AcquireLock. /// /// For more information, see the "Extending and Embedding" section /// of the Python documentation on www.python.org. /// </remarks> public static IntPtr AcquireLock() { return(Runtime.PyGILState_Ensure()); }