/// <summary> /// Given a Python object, return the associated managed object or null. /// </summary> internal static ManagedType GetManagedObject(IntPtr ob) { if (ob != IntPtr.Zero) { IntPtr tp = Runtime.PyObject_TYPE(ob); if (tp == Runtime.PyTypeType || tp == Runtime.PyCLRMetaType) { tp = ob; } var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Managed) != 0) { IntPtr op = tp == ob ? Marshal.ReadIntPtr(tp, TypeOffset.magic()) : Marshal.ReadIntPtr(ob, ObjectOffset.magic(tp)); if (op == IntPtr.Zero) { return(null); } var gc = (GCHandle)op; return((ManagedType)gc.Target); } } return(null); }
// Called from Converter.ToPython for types that are python subclasses of managed types. // The referenced python object is returned instead of a new wrapper. internal static IntPtr ToPython(IPythonDerivedType obj) { // derived types have a __pyobj__ field that gets set to the python // object in the overriden constructor FieldInfo fi = obj.GetType().GetField("__pyobj__"); CLRObject self = (CLRObject)fi.GetValue(obj); Runtime.Incref(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) { GCHandle gc = GCHandle.Alloc(self, GCHandleType.Normal); Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.magic(self.tpHandle), (IntPtr)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); }
public ExtensionType() { // Create a new PyObject whose type is a generated type that is // implemented by the particular concrete ExtensionType subclass. // The Python instance object is related to an instance of a // particular concrete subclass with a hidden CLR gchandle. IntPtr tp = TypeManager.GetTypeHandle(GetType()); //int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt); //if (rc > 1050) //{ // DebugUtil.Print("tp is: ", tp); // DebugUtil.DumpType(tp); //} IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); GCHandle gc = GCHandle.Alloc(this); Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc); // We have to support gc because the type machinery makes it very // hard not to - but we really don't have a need for it in most // concrete extension types, so untrack the object to save calls // from Python into the managed runtime that are pure overhead. Runtime.PyObject_GC_UnTrack(py); // Steals a ref to tpHandle. tpHandle = tp; pyHandle = py; gcHandle = gc; }
internal CLRObject(object ob, IntPtr tp) { IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); long flags = Util.ReadCLong(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) != 0) { IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.DictOffset(tp)); if (dict == IntPtr.Zero) { dict = Runtime.PyDict_New(); Marshal.WriteIntPtr(py, ObjectOffset.DictOffset(tp), dict); } } GCHandle gc = GCHandle.Alloc(this); Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc); tpHandle = tp; pyHandle = py; gcHandle = gc; inst = ob; // Fix the BaseException args (and __cause__ in case of Python 3) // slot if wrapping a CLR exception Exceptions.SetArgsAndCause(py); }
internal CLRObject(object ob, IntPtr tp) { System.Diagnostics.Debug.Assert(tp != IntPtr.Zero); IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); long flags = Util.ReadCLong(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) != 0) { IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp)); if (dict == IntPtr.Zero) { dict = Runtime.PyDict_New(); Marshal.WriteIntPtr(py, ObjectOffset.TypeDictOffset(tp), dict); } } GCHandle gc = AllocGCHandle(TrackTypes.Wrapper); Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), GCHandle.ToIntPtr(gc)); tpHandle = tp; pyHandle = py; inst = ob; // for performance before calling SetArgsAndCause() lets check if we are an exception if (inst is Exception) { // Fix the BaseException args (and __cause__ in case of Python 3) // slot if wrapping a CLR exception Exceptions.SetArgsAndCause(py); } }
protected override void OnLoad(InterDomainContext context) { base.OnLoad(context); GCHandle gc = AllocGCHandle(TrackTypes.Wrapper); Marshal.WriteIntPtr(pyHandle, ObjectOffset.magic(tpHandle), (IntPtr)gc); }
void SetupGc() { GCHandle gc = AllocGCHandle(TrackTypes.Extension); Marshal.WriteIntPtr(pyHandle, ObjectOffset.magic(tpHandle), (IntPtr)gc); // We have to support gc because the type machinery makes it very // hard not to - but we really don't have a need for it in most // concrete extension types, so untrack the object to save calls // from Python into the managed runtime that are pure overhead. Runtime.PyObject_GC_UnTrack(pyHandle); }
new public static void tp_dealloc(IntPtr ob) { CLRObject self = (CLRObject)GetManagedObject(ob); // don't let the python GC destroy this object Runtime.PyObject_GC_UnTrack(self.pyHandle); // The python should now have a ref count of 0, but we don't actually want to // deallocate the object until the C# object that references it is destroyed. // So we don't call PyObject_GC_Del here and instead we set the python // reference to a weak reference so that the C# object can be collected. GCHandle gc = GCHandle.Alloc(self, GCHandleType.Weak); Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.magic(self.tpHandle), (IntPtr)gc); self.gcHandle.Free(); self.gcHandle = gc; }
internal IntPtr tpHandle; // PyType * //==================================================================== // Given a Python object, return the associated managed object or null. //==================================================================== internal static ManagedType GetManagedObject(IntPtr ob) { if (ob != IntPtr.Zero) { IntPtr tp = Runtime.PyObject_TYPE(ob); if (tp == Runtime.PyTypeType || tp == Runtime.PyCLRMetaType) { tp = ob; } int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Managed) != 0) { IntPtr op = (tp == ob) ? Marshal.ReadIntPtr(tp, TypeOffset.magic()) : Marshal.ReadIntPtr(ob, ObjectOffset.magic()); GCHandle gc = (GCHandle)op; return((ManagedType)gc.Target); } // In certain situations, we need to recognize a wrapped // exception class and be willing to unwrap the class :( if (Runtime.wrap_exceptions) { IntPtr e = Exceptions.UnwrapExceptionClass(ob); if ((e != IntPtr.Zero) && (e != ob)) { ManagedType m = GetManagedObject(e); Runtime.Decref(e); return(m); } } } return(null); }
internal CLRObject(Object ob, IntPtr tp) : base() { IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) != 0) { IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.DictOffset(tp)); if (dict == IntPtr.Zero) { dict = Runtime.PyDict_New(); Marshal.WriteIntPtr(py, ObjectOffset.DictOffset(tp), dict); } } GCHandle gc = GCHandle.Alloc(this); Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc); this.tpHandle = tp; this.pyHandle = py; this.gcHandle = gc; inst = ob; }