private PyDict_SetItem ( IntPtr pointer, IntPtr key, IntPtr value ) : int | ||
pointer | IntPtr | |
key | IntPtr | |
value | IntPtr | |
return | int |
/// <summary> /// The following CreateType implementations do the necessary work to /// create Python types to represent managed extension types, reflected /// types, subclasses of reflected types and the managed metatype. The /// dance is slightly different for each kind of type due to different /// behavior needed and the desire to have the existing Python runtime /// do as much of the allocation and initialization work as possible. /// </summary> internal static IntPtr CreateType(Type impl) { IntPtr type = AllocateTypeObject(impl.Name); int ob_size = ObjectOffset.Size(type); // Set tp_basicsize to the size of our managed instance objects. Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); var offset = (IntPtr)ObjectOffset.TypeDictOffset(type); Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); SlotsHolder slotsHolder = CreateSolotsHolder(type); InitializeSlots(type, impl, slotsHolder); int flags = TypeFlags.Default | TypeFlags.Managed | TypeFlags.HeapType | TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, flags); if (Runtime.PyType_Ready(type) != 0) { throw new PythonException(); } IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod); Runtime.XDecref(mod); InitMethods(type, impl); return(type); }
public override ValueType Execute(ValueType arg) { const string code = @" from Python.EmbeddingTest.Domain import MyClass def test_obj_call(): obj = MyClass() obj.Method() obj.StaticMethod() obj.Property = 1 obj.Field = 10 test_obj_call() "; const string name = "test_domain_reload_mod"; using (Py.GIL()) { // Create a new module IntPtr module = PyRuntime.PyModule_New(name); Assert.That(module != IntPtr.Zero); IntPtr globals = PyRuntime.PyObject_GetAttr(module, PyIdentifier.__dict__); Assert.That(globals != IntPtr.Zero); try { // import builtins // module.__dict__[__builtins__] = builtins int res = PyRuntime.PyDict_SetItem(globals, PyIdentifier.__builtins__, PyRuntime.PyEval_GetBuiltins()); PythonException.ThrowIfIsNotZero(res); // Execute the code in the module's scope PythonEngine.Exec(code, globals); // import sys // modules = sys.modules IntPtr modules = PyRuntime.PyImport_GetModuleDict(); // modules[name] = module res = PyRuntime.PyDict_SetItemString(modules, name, module); PythonException.ThrowIfIsNotZero(res); } catch { PyRuntime.XDecref(module); throw; } finally { PyRuntime.XDecref(globals); } return(module); } }
public new static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { var managedKey = Runtime.GetManagedString(key); if ((settableAttributes.Contains(managedKey)) || (ManagedType.GetManagedObject(val)?.GetType() == typeof(ModuleObject))) { var self = (ModuleObject)ManagedType.GetManagedObject(ob); return(Runtime.PyDict_SetItem(self.dict, key, val)); } return(ExtensionType.tp_setattro(ob, key, val)); }
internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) { // Utility to create a subtype of a std Python type, but with // a managed type able to override implementation IntPtr type = AllocateTypeObject(name, metatype: Runtime.PyTypeType); //Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize); //Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); //IntPtr offset = (IntPtr)ObjectOffset.ob_dict; //Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); //IntPtr dc = Runtime.PyDict_Copy(dict); //Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc); Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); Runtime.XIncref(base_); var flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); CopySlot(base_, type, TypeOffset.tp_traverse); CopySlot(base_, type, TypeOffset.tp_clear); CopySlot(base_, type, TypeOffset.tp_is_gc); SlotsHolder slotsHolder = CreateSolotsHolder(type); InitializeSlots(type, impl, slotsHolder); if (Runtime.PyType_Ready(type) != 0) { throw new PythonException(); } IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); Runtime.PyDict_SetItem(tp_dict, PyIdentifier.__module__, mod); // The type has been modified after PyType_Ready has been called // Refresh the type Runtime.PyType_Modified(type); return(type); }
private static void RestoreDotNetModules(Dictionary <PyString, PyObject> modules) { var pyMoudles = Runtime.PyImport_GetModuleDict(); foreach (var item in modules) { var moduleName = item.Key; var module = item.Value; int res = Runtime.PyDict_SetItem(pyMoudles, moduleName, module); PythonException.ThrowIfIsNotZero(res); item.Key.Dispose(); item.Value.Dispose(); } modules.Clear(); }
/// <summary> /// The following CreateType implementations do the necessary work to /// create Python types to represent managed extension types, reflected /// types, subclasses of reflected types and the managed metatype. The /// dance is slightly different for each kind of type due to different /// behavior needed and the desire to have the existing Python runtime /// do as much of the allocation and initialization work as possible. /// </summary> internal static unsafe IntPtr CreateType(Type impl) { IntPtr type = AllocateTypeObject(impl.Name, metatype: Runtime.PyCLRMetaType); IntPtr base_ = impl == typeof(CLRModule) ? Runtime.PyModuleType : Runtime.PyBaseObjectType; int newFieldOffset = InheritOrAllocateStandardFields(type, base_); int tp_clr_inst_offset = newFieldOffset; newFieldOffset += IntPtr.Size; int ob_size = newFieldOffset; // Set tp_basicsize to the size of our managed instance objects. Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); Marshal.WriteInt32(type, ManagedType.Offsets.tp_clr_inst_offset, tp_clr_inst_offset); Marshal.WriteIntPtr(type, TypeOffset.tp_new, (IntPtr)Runtime.Delegates.PyType_GenericNew); SlotsHolder slotsHolder = CreateSolotsHolder(type); InitializeSlots(type, impl, slotsHolder); var flags = TypeFlags.Default | TypeFlags.HasClrInstance | TypeFlags.HeapType | TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); if (Runtime.PyType_Ready(type) != 0) { throw new PythonException(); } var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict)); var mod = NewReference.DangerousFromPointer(Runtime.PyString_FromString("CLR")); Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod); mod.Dispose(); InitMethods(type, impl); // The type has been modified after PyType_Ready has been called // Refresh the type Runtime.PyType_Modified(type); return(type); }
public ModuleObject(string name) { if (name == string.Empty) { throw new ArgumentException("Name must not be empty!"); } moduleName = name; cache = new Dictionary <string, ManagedType>(); _namespace = name; // Use the filename from any of the assemblies just so there's something for // anything that expects __file__ to be set. var filename = "unknown"; var docstring = "Namespace containing types from the following assemblies:\n\n"; foreach (Assembly a in AssemblyManager.GetAssemblies(name)) { if (!a.IsDynamic && a.Location != null) { filename = a.Location; } docstring += "- " + a.FullName + "\n"; } dict = Runtime.PyDict_New(); IntPtr pyname = Runtime.PyString_FromString(moduleName); IntPtr pyfilename = Runtime.PyString_FromString(filename); IntPtr pydocstring = Runtime.PyString_FromString(docstring); IntPtr pycls = TypeManager.GetTypeHandle(GetType()); Runtime.PyDict_SetItem(dict, PyIdentifier.__name__, pyname); Runtime.PyDict_SetItem(dict, PyIdentifier.__file__, pyfilename); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, pydocstring); Runtime.PyDict_SetItem(dict, PyIdentifier.__class__, pycls); Runtime.XDecref(pyname); Runtime.XDecref(pyfilename); Runtime.XDecref(pydocstring); Runtime.XIncref(dict); SetObjectDict(pyHandle, dict); InitializeModuleMembers(); }
/// <summary> /// Constructor /// </summary> /// <remarks> /// Create a scope based on a Python Module. /// </remarks> internal PyScope(ref NewReference ptr, PyScopeManager manager) { if (!Runtime.PyType_IsSubtype(Runtime.PyObject_TYPE(ptr), Runtime.PyModuleType)) { throw new PyScopeException("object is not a module"); } Manager = manager ?? PyScopeManager.Global; obj = ptr.MoveToPyObject(); //Refcount of the variables not increase variables = Runtime.PyModule_GetDict(Reference).DangerousGetAddress(); PythonException.ThrowIfIsNull(variables); int res = Runtime.PyDict_SetItem( VarsRef, PyIdentifier.__builtins__, Runtime.PyEval_GetBuiltins() ); PythonException.ThrowIfIsNotZero(res); this.Name = this.Get <string>("__name__"); }
public ModuleObject(string name) { if (name == string.Empty) { throw new ArgumentException("Name must not be empty!"); } moduleName = name; cache = new Dictionary <string, ManagedType>(); _namespace = name; // Use the filename from any of the assemblies just so there's something for // anything that expects __file__ to be set. var filename = "unknown"; var docstring = "Namespace containing types from the following assemblies:\n\n"; foreach (Assembly a in AssemblyManager.GetAssemblies(name)) { if (!a.IsDynamic && a.Location != null) { filename = a.Location; } docstring += "- " + a.FullName + "\n"; } var dictRef = Runtime.PyObject_GenericGetDict(ObjectReference); PythonException.ThrowIfIsNull(dictRef); dict = dictRef.DangerousMoveToPointer(); using var pyname = NewReference.DangerousFromPointer(Runtime.PyString_FromString(moduleName)); using var pyfilename = NewReference.DangerousFromPointer(Runtime.PyString_FromString(filename)); using var pydocstring = NewReference.DangerousFromPointer(Runtime.PyString_FromString(docstring)); BorrowedReference pycls = TypeManager.GetTypeReference(GetType()); Runtime.PyDict_SetItem(DictRef, PyIdentifier.__name__, pyname); Runtime.PyDict_SetItem(DictRef, PyIdentifier.__file__, pyfilename); Runtime.PyDict_SetItem(DictRef, PyIdentifier.__doc__, pydocstring); Runtime.PyDict_SetItem(DictRef, PyIdentifier.__class__, pycls); InitializeModuleMembers(); }
/// <summary> /// The following CreateType implementations do the necessary work to /// create Python types to represent managed extension types, reflected /// types, subclasses of reflected types and the managed metatype. The /// dance is slightly different for each kind of type due to different /// behavior needed and the desire to have the existing Python runtime /// do as much of the allocation and initialization work as possible. /// </summary> internal static IntPtr CreateType(Type impl) { IntPtr type = AllocateTypeObject(impl.Name, metatype: Runtime.PyTypeType); int ob_size = ObjectOffset.Size(type); // Set tp_basicsize to the size of our managed instance objects. Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); var offset = (IntPtr)ObjectOffset.TypeDictOffset(type); Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); SlotsHolder slotsHolder = CreateSolotsHolder(type); InitializeSlots(type, impl, slotsHolder); var flags = TypeFlags.Default | TypeFlags.Managed | TypeFlags.HeapType | TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); if (Runtime.PyType_Ready(type) != 0) { throw new PythonException(); } var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict)); var mod = NewReference.DangerousFromPointer(Runtime.PyString_FromString("CLR")); Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod); mod.Dispose(); InitMethods(type, impl); // The type has been modified after PyType_Ready has been called // Refresh the type Runtime.PyType_Modified(type); return(type); }
private static void InitClassBase(Type type, ClassBase impl) { // First, we introspect the managed type and build some class // information, including generating the member descriptors // that we'll be putting in the Python class __dict__. ClassInfo info = GetClassInfo(type); impl.indexer = info.indexer; impl.richcompare = new Dictionary <int, MethodObject>(); // Now we allocate the Python type object to reflect the given // managed type, filling the Python type slots with thunks that // point to the managed methods providing the implementation. IntPtr tp = TypeManager.GetTypeHandle(impl, type); // Finally, initialize the class __dict__ and return the object. var dict = new BorrowedReference(Marshal.ReadIntPtr(tp, TypeOffset.tp_dict)); if (impl.dotNetMembers == null) { impl.dotNetMembers = new List <string>(); } IDictionaryEnumerator iter = info.members.GetEnumerator(); while (iter.MoveNext()) { var item = (ManagedType)iter.Value; var name = (string)iter.Key; impl.dotNetMembers.Add(name); Runtime.PyDict_SetItemString(dict, name, item.ObjectReference); // Decref the item now that it's been used. item.DecrRefCount(); if (ClassBase.CilToPyOpMap.TryGetValue(name, out var pyOp)) { impl.richcompare.Add(pyOp, (MethodObject)item); } } // If class has constructors, generate an __doc__ attribute. NewReference doc = default; Type marker = typeof(DocStringAttribute); var attrs = (Attribute[])type.GetCustomAttributes(marker, false); if (attrs.Length != 0) { var attr = (DocStringAttribute)attrs[0]; string docStr = attr.DocString; doc = NewReference.DangerousFromPointer(Runtime.PyString_FromString(docStr)); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc); } var co = impl as ClassObject; // If this is a ClassObject AND it has constructors, generate a __doc__ attribute. // required that the ClassObject.ctors be changed to internal if (co != null) { if (co.NumCtors > 0) { // Implement Overloads on the class object if (!CLRModule._SuppressOverloads) { var ctors = new ConstructorBinding(type, tp, co.binder); // ExtensionType types are untracked, so don't Incref() them. // TODO: deprecate __overloads__ soon... Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.ObjectReference); Runtime.PyDict_SetItem(dict, PyIdentifier.Overloads, ctors.ObjectReference); ctors.DecrRefCount(); } // don't generate the docstring if one was already set from a DocStringAttribute. if (!CLRModule._SuppressDocs && doc.IsNull()) { doc = co.GetDocString(); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc); } } } doc.Dispose(); // The type has been modified after PyType_Ready has been called // Refresh the type Runtime.PyType_Modified(tp); }
internal static IntPtr CreateType(ManagedType impl, Type clrType) { // Cleanup the type name to get rid of funny nested type names. string name = $"clr.{clrType.FullName}"; int i = name.LastIndexOf('+'); if (i > -1) { name = name.Substring(i + 1); } i = name.LastIndexOf('.'); if (i > -1) { name = name.Substring(i + 1); } IntPtr base_ = IntPtr.Zero; int ob_size = ObjectOffset.Size(Runtime.PyTypeType); // XXX Hack, use a different base class for System.Exception // Python 2.5+ allows new style class exceptions but they *must* // subclass BaseException (or better Exception). if (typeof(Exception).IsAssignableFrom(clrType)) { ob_size = ObjectOffset.Size(Exceptions.Exception); } int tp_dictoffset = ob_size + ManagedDataOffsets.ob_dict; if (clrType == typeof(Exception)) { base_ = Exceptions.Exception; } else if (clrType.BaseType != null) { ClassBase bc = ClassManager.GetClass(clrType.BaseType); base_ = bc.pyHandle; } IntPtr type = AllocateTypeObject(name, Runtime.PyCLRMetaType); Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType); Runtime.XIncref(Runtime.PyCLRMetaType); Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, (IntPtr)tp_dictoffset); // we want to do this after the slot stuff above in case the class itself implements a slot method SlotsHolder slotsHolder = CreateSolotsHolder(type); InitializeSlots(type, impl.GetType(), slotsHolder); if (Marshal.ReadIntPtr(type, TypeOffset.mp_length) == IntPtr.Zero && mp_length_slot.CanAssign(clrType)) { InitializeSlot(type, TypeOffset.mp_length, mp_length_slot.Method, slotsHolder); } if (!typeof(IEnumerable).IsAssignableFrom(clrType) && !typeof(IEnumerator).IsAssignableFrom(clrType)) { // The tp_iter slot should only be set for enumerable types. Marshal.WriteIntPtr(type, TypeOffset.tp_iter, IntPtr.Zero); } // Only set mp_subscript and mp_ass_subscript for types with indexers if (impl is ClassBase cb) { if (!(impl is ArrayObject)) { if (cb.indexer == null || !cb.indexer.CanGet) { Marshal.WriteIntPtr(type, TypeOffset.mp_subscript, IntPtr.Zero); } if (cb.indexer == null || !cb.indexer.CanSet) { Marshal.WriteIntPtr(type, TypeOffset.mp_ass_subscript, IntPtr.Zero); } } } else { Marshal.WriteIntPtr(type, TypeOffset.mp_subscript, IntPtr.Zero); Marshal.WriteIntPtr(type, TypeOffset.mp_ass_subscript, IntPtr.Zero); } if (base_ != IntPtr.Zero) { Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); Runtime.XIncref(base_); } const TypeFlags flags = TypeFlags.Default | TypeFlags.Managed | TypeFlags.HeapType | TypeFlags.BaseType | TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); OperatorMethod.FixupSlots(type, clrType); // Leverage followup initialization from the Python runtime. Note // that the type of the new type must PyType_Type at the time we // call this, else PyType_Ready will skip some slot initialization. if (Runtime.PyType_Ready(type) != 0) { throw new PythonException(); } var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict)); string mn = clrType.Namespace ?? ""; var mod = NewReference.DangerousFromPointer(Runtime.PyString_FromString(mn)); Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod); mod.Dispose(); // Hide the gchandle of the implementation in a magic type slot. GCHandle gc = impl.AllocGCHandle(); Marshal.WriteIntPtr(type, TypeOffset.magic(), (IntPtr)gc); // Set the handle attributes on the implementing instance. impl.tpHandle = type; impl.pyHandle = type; //DebugUtil.DumpType(type); return(type); }
/// <summary> /// Initialize Method /// </summary> /// <remarks> /// Initialize the Python runtime. It is safe to call this method /// more than once, though initialization will only happen on the /// first call. It is *not* necessary to hold the Python global /// interpreter lock (GIL) to call this method. /// initSigs can be set to 1 to do default python signal configuration. This will override the way signals are handled by the application. /// </remarks> public static void Initialize(IEnumerable <string> args, bool setSysArgv = true, bool initSigs = false) { if (!initialized) { // Creating the delegateManager MUST happen before Runtime.Initialize // is called. If it happens afterwards, DelegateManager's CodeGenerator // throws an exception in its ctor. This exception is eaten somehow // during an initial "import clr", and the world ends shortly thereafter. // This is probably masking some bad mojo happening somewhere in Runtime.Initialize(). delegateManager = new DelegateManager(); Runtime.Initialize(initSigs); initialized = true; Exceptions.Clear(); // Make sure we clean up properly on app domain unload. AppDomain.CurrentDomain.DomainUnload += OnDomainUnload; // Remember to shut down the runtime. AddShutdownHandler(Runtime.Shutdown); // The global scope gets used implicitly quite early on, remember // to clear it out when we shut down. AddShutdownHandler(PyScopeManager.Global.Clear); if (setSysArgv) { Py.SetArgv(args); } // register the atexit callback (this doesn't use Py_AtExit as the C atexit // callbacks are called after python is fully finalized but the python ones // are called while the python engine is still running). string code = "import atexit, clr\n" + "atexit.register(clr._AtExit)\n"; PythonEngine.Exec(code); // Load the clr.py resource into the clr module IntPtr clr = Python.Runtime.ImportHook.GetCLRModule(); IntPtr clr_dict = Runtime.PyModule_GetDict(clr); var locals = new PyDict(); try { IntPtr module = Runtime.PyImport_AddModule("clr._extras"); IntPtr module_globals = Runtime.PyModule_GetDict(module); IntPtr builtins = Runtime.PyEval_GetBuiltins(); Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream stream = assembly.GetManifestResourceStream("clr.py")) using (var reader = new StreamReader(stream)) { // add the contents of clr.py to the module string clr_py = reader.ReadToEnd(); Exec(clr_py, module_globals, locals.Handle); } // add the imported module to the clr module, and copy the API functions // and decorators into the main clr module. Runtime.PyDict_SetItemString(clr_dict, "_extras", module); foreach (PyObject key in locals.Keys()) { if (!key.ToString().StartsWith("_") || key.ToString().Equals("__version__")) { PyObject value = locals[key]; Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle); value.Dispose(); } key.Dispose(); } } finally { locals.Dispose(); } } }
private static void InitClassBase(Type type, ClassBase impl) { // First, we introspect the managed type and build some class // information, including generating the member descriptors // that we'll be putting in the Python class __dict__. ClassInfo info = GetClassInfo(type); impl.indexer = info.indexer; // Now we allocate the Python type object to reflect the given // managed type, filling the Python type slots with thunks that // point to the managed methods providing the implementation. IntPtr tp = TypeManager.GetTypeHandle(impl, type); // Finally, initialize the class __dict__ and return the object. IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict); IDictionaryEnumerator iter = info.members.GetEnumerator(); while (iter.MoveNext()) { var item = (ManagedType)iter.Value; var name = (string)iter.Key; Runtime.PyDict_SetItemString(dict, name, item.pyHandle); // Decref the item now that it's been used. item.DecrRefCount(); } // If class has constructors, generate an __doc__ attribute. IntPtr doc = IntPtr.Zero; Type marker = typeof(DocStringAttribute); var attrs = (Attribute[])type.GetCustomAttributes(marker, false); if (attrs.Length == 0) { doc = IntPtr.Zero; } else { var attr = (DocStringAttribute)attrs[0]; string docStr = attr.DocString; doc = Runtime.PyString_FromString(docStr); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc); Runtime.XDecref(doc); } var co = impl as ClassObject; // If this is a ClassObject AND it has constructors, generate a __doc__ attribute. // required that the ClassObject.ctors be changed to internal if (co != null) { if (co.ctors.Length > 0) { // Implement Overloads on the class object if (!CLRModule._SuppressOverloads) { var ctors = new ConstructorBinding(type, tp, co.binder); // ExtensionType types are untracked, so don't Incref() them. // TODO: deprecate __overloads__ soon... Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.pyHandle); Runtime.PyDict_SetItem(dict, PyIdentifier.Overloads, ctors.pyHandle); ctors.DecrRefCount(); } // don't generate the docstring if one was already set from a DocStringAttribute. if (!CLRModule._SuppressDocs && doc == IntPtr.Zero) { doc = co.GetDocString(); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc); Runtime.XDecref(doc); } } } }
/// <summary> /// Initialize Method /// </summary> /// /// <remarks> /// Initialize the Python runtime. It is safe to call this method /// more than once, though initialization will only happen on the /// first call. It is *not* necessary to hold the Python global /// interpreter lock (GIL) to call this method. /// </remarks> public static void Initialize() { if (!initialized) { // Creating the delegateManager MUST happen before Runtime.Initialize // is called. If it happens afterwards, DelegateManager's CodeGenerator // throws an exception in its ctor. This exception is eaten somehow // during an initial "import clr", and the world ends shortly thereafter. // This is probably masking some bad mojo happening somewhere in Runtime.Initialize(). delegateManager = new DelegateManager(); Runtime.Initialize(); initialized = true; Exceptions.Clear(); // register the atexit callback (this doesn't use Py_AtExit as the C atexit // callbacks are called after python is fully finalized but the python ones // are called while the python engine is still running). string code = "import atexit, clr\n" + "atexit.register(clr._AtExit)\n"; PyObject r = PythonEngine.RunString(code); if (r != null) { r.Dispose(); } // Load the clr.py resource into the clr module IntPtr clr = Python.Runtime.ImportHook.GetCLRModule(); IntPtr clr_dict = Runtime.PyModule_GetDict(clr); PyDict locals = new PyDict(); try { IntPtr module = Runtime.PyImport_AddModule("clr._extras"); IntPtr module_globals = Runtime.PyModule_GetDict(module); IntPtr builtins = Runtime.PyEval_GetBuiltins(); Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); var assembly = Assembly.GetExecutingAssembly(); using (Stream stream = assembly.GetManifestResourceStream("clr.py")) using (StreamReader reader = new StreamReader(stream)) { // add the contents of clr.py to the module string clr_py = reader.ReadToEnd(); PyObject result = RunString(clr_py, module_globals, locals.Handle); if (null == result) { throw new PythonException(); } result.Dispose(); } // add the imported module to the clr module, and copy the API functions // and decorators into the main clr module. Runtime.PyDict_SetItemString(clr_dict, "_extras", module); foreach (PyObject key in locals.Keys()) { if (!key.ToString().StartsWith("_")) { PyObject value = locals[key]; Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle); value.Dispose(); } key.Dispose(); } } finally { locals.Dispose(); } } }