//=================================================================== // Return the clr python module (new reference) //=================================================================== public static IntPtr GetCLRModule(IntPtr?fromList = null) { root.InitializePreload(); #if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) // update the module dictionary with the contents of the root dictionary root.LoadNames(); IntPtr py_mod_dict = Runtime.PyModule_GetDict(py_clr_module); IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject** clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr)); Runtime.PyDict_Update(py_mod_dict, clr_dict); // find any items from the fromlist and get them from the root if they're not // aleady in the module dictionary if (fromList != null && fromList != IntPtr.Zero) { if (Runtime.PyTuple_Check(fromList.GetValueOrDefault())) { Runtime.Incref(py_mod_dict); using (PyDict mod_dict = new PyDict(py_mod_dict)) { Runtime.Incref(fromList.GetValueOrDefault()); using (PyTuple from = new PyTuple(fromList.GetValueOrDefault())) { foreach (PyObject item in from) { if (mod_dict.HasKey(item)) { continue; } string s = item.AsManagedObject(typeof(string)) as string; if (null == s) { continue; } ManagedType attr = root.GetAttribute(s, true); if (null == attr) { continue; } Runtime.Incref(attr.pyHandle); using (PyObject obj = new PyObject(attr.pyHandle)) { mod_dict.SetItem(s, obj); } } } } } } Runtime.Incref(py_clr_module); return(py_clr_module); #else Runtime.Incref(root.pyHandle); return(root.pyHandle); #endif }
/// <summary> /// Return the clr python module (new reference) /// </summary> public static unsafe NewReference GetCLRModule(BorrowedReference fromList = default) { root.InitializePreload(); // update the module dictionary with the contents of the root dictionary root.LoadNames(); BorrowedReference py_mod_dict = Runtime.PyModule_GetDict(ClrModuleReference); using (var clr_dict = Runtime.PyObject_GenericGetDict(root.ObjectReference)) { Runtime.PyDict_Update(py_mod_dict, clr_dict); } // find any items from the from list and get them from the root if they're not // already in the module dictionary if (fromList != null) { if (Runtime.PyTuple_Check(fromList)) { using var mod_dict = new PyDict(py_mod_dict); using var from = new PyTuple(fromList); foreach (PyObject item in from) { if (mod_dict.HasKey(item)) { continue; } var s = item.AsManagedObject(typeof(string)) as string; if (s == null) { continue; } ManagedType attr = root.GetAttribute(s, true); if (attr == null) { continue; } Runtime.XIncref(attr.pyHandle); using (var obj = new PyObject(attr.pyHandle)) { mod_dict.SetItem(s, obj); } } } } Runtime.XIncref(py_clr_module); return(NewReference.DangerousFromPointer(py_clr_module)); }
//=================================================================== // Return the clr python module (new reference) //=================================================================== public static IntPtr GetCLRModule(IntPtr? fromList = null) { root.InitializePreload(); #if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) // update the module dictionary with the contents of the root dictionary root.LoadNames(); IntPtr py_mod_dict = Runtime.PyModule_GetDict(py_clr_module); IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject** clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr)); Runtime.PyDict_Update(py_mod_dict, clr_dict); // find any items from the fromlist and get them from the root if they're not // aleady in the module dictionary if (fromList != null && fromList != IntPtr.Zero) { if (Runtime.PyTuple_Check(fromList.GetValueOrDefault())) { Runtime.XIncref(py_mod_dict); using(PyDict mod_dict = new PyDict(py_mod_dict)) { Runtime.XIncref(fromList.GetValueOrDefault()); using (PyTuple from = new PyTuple(fromList.GetValueOrDefault())) { foreach (PyObject item in from) { if (mod_dict.HasKey(item)) continue; string s = item.AsManagedObject(typeof(string)) as string; if (null == s) continue; ManagedType attr = root.GetAttribute(s, true); if (null == attr) continue; Runtime.XIncref(attr.pyHandle); using (PyObject obj = new PyObject(attr.pyHandle)) { mod_dict.SetItem(s, obj); } } } } } } Runtime.XIncref(py_clr_module); return py_clr_module; #else Runtime.XIncref(root.pyHandle); return root.pyHandle; #endif }
//==================================================================== // Metatype __new__ implementation. This is called to create a new // class / type when a reflected class is subclassed. //==================================================================== public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) { int len = Runtime.PyTuple_Size(args); if (len < 3) { return Exceptions.RaiseTypeError("invalid argument list"); } IntPtr name = Runtime.PyTuple_GetItem(args, 0); IntPtr bases = Runtime.PyTuple_GetItem(args, 1); IntPtr dict = Runtime.PyTuple_GetItem(args, 2); // We do not support multiple inheritance, so the bases argument // should be a 1-item tuple containing the type we are subtyping. // That type must itself have a managed implementation. We check // that by making sure its metatype is the CLR metatype. if (Runtime.PyTuple_Size(bases) != 1) { return Exceptions.RaiseTypeError( "cannot use multiple inheritance with managed classes" ); } IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0); IntPtr mt = Runtime.PyObject_TYPE(base_type); if (!((mt == PyCLRMetaType) || (mt == Runtime.PyTypeType))) { return Exceptions.RaiseTypeError("invalid metatype"); } // Ensure that the reflected type is appropriate for subclassing, // disallowing subclassing of delegates, enums and array types. ClassBase cb = GetManagedObject(base_type) as ClassBase; if (cb != null) { if (!cb.CanSubclass()) { return Exceptions.RaiseTypeError( "delegates, enums and array types cannot be subclassed" ); } } IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__"); if (slots != IntPtr.Zero) { return Exceptions.RaiseTypeError( "subclasses of managed classes do not support __slots__" ); } // If __assembly__ or __namespace__ are in the class dictionary then create // a managed sub type. // This creates a new managed type that can be used from .net to call back // into python. if (IntPtr.Zero != dict) { Runtime.XIncref(dict); using (PyDict clsDict = new PyDict(dict)) { if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__")) return TypeManager.CreateSubType(name, base_type, dict); } } // otherwise just create a basic type without reflecting back into the managed side. IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType, TypeOffset.tp_new); IntPtr type = NativeCall.Call_3(func, tp, args, kw); if (type == IntPtr.Zero) { return IntPtr.Zero; } int flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.Subclass; flags |= TypeFlags.HaveGC; Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags); TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc); // Hmm - the standard subtype_traverse, clear look at ob_size to // do things, so to allow gc to work correctly we need to move // our hidden handle out of ob_size. Then, in theory we can // comment this out and still not crash. TypeManager.CopySlot(base_type, type, TypeOffset.tp_traverse); TypeManager.CopySlot(base_type, type, TypeOffset.tp_clear); // for now, move up hidden handle... IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic()); Marshal.WriteIntPtr(type, TypeOffset.magic(), gc); return type; }
/// <summary> /// Metatype __new__ implementation. This is called to create a new /// class / type when a reflected class is subclassed. /// </summary> public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) { int len = Runtime.PyTuple_Size(args); if (len < 3) { return(Exceptions.RaiseTypeError("invalid argument list")); } IntPtr name = Runtime.PyTuple_GetItem(args, 0); IntPtr bases = Runtime.PyTuple_GetItem(args, 1); IntPtr dict = Runtime.PyTuple_GetItem(args, 2); // We do not support multiple inheritance, so the bases argument // should be a 1-item tuple containing the type we are subtyping. // That type must itself have a managed implementation. We check // that by making sure its metatype is the CLR metatype. if (Runtime.PyTuple_Size(bases) != 1) { return(Exceptions.RaiseTypeError("cannot use multiple inheritance with managed classes")); } IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0); IntPtr mt = Runtime.PyObject_TYPE(base_type); if (!(mt == PyCLRMetaType || mt == Runtime.PyTypeType)) { return(Exceptions.RaiseTypeError("invalid metatype")); } // Ensure that the reflected type is appropriate for subclassing, // disallowing subclassing of delegates, enums and array types. var cb = GetManagedObject(base_type) as ClassBase; if (cb != null) { if (!cb.CanSubclass()) { return(Exceptions.RaiseTypeError("delegates, enums and array types cannot be subclassed")); } } IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__"); if (slots != IntPtr.Zero) { return(Exceptions.RaiseTypeError("subclasses of managed classes do not support __slots__")); } // If __assembly__ or __namespace__ are in the class dictionary then create // a managed sub type. // This creates a new managed type that can be used from .net to call back // into python. if (IntPtr.Zero != dict) { Runtime.XIncref(dict); using (var clsDict = new PyDict(dict)) { if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__")) { return(TypeManager.CreateSubType(name, base_type, dict)); } } } // otherwise just create a basic type without reflecting back into the managed side. IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType, TypeOffset.tp_new); IntPtr type = NativeCall.Call_3(func, tp, args, kw); if (type == IntPtr.Zero) { return(IntPtr.Zero); } int flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.Subclass; flags |= TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, flags); TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc); // Hmm - the standard subtype_traverse, clear look at ob_size to // do things, so to allow gc to work correctly we need to move // our hidden handle out of ob_size. Then, in theory we can // comment this out and still not crash. TypeManager.CopySlot(base_type, type, TypeOffset.tp_traverse); TypeManager.CopySlot(base_type, type, TypeOffset.tp_clear); // for now, move up hidden handle... IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic()); Marshal.WriteIntPtr(type, TypeOffset.magic(), gc); return(type); }