private PyObject GetPythonActionContext(ActionContext context) { PyDict dict = new PyDict(); PyDict specialKeyStateDict = new PyDict(); specialKeyStateDict["CtrlPressed"] = new PyString(context.SpecialKeyState.CtrlPressed.ToString()); specialKeyStateDict["AltPressed"] = new PyString(context.SpecialKeyState.AltPressed.ToString()); specialKeyStateDict["WinPressed"] = new PyString(context.SpecialKeyState.WinPressed.ToString()); specialKeyStateDict["ShiftPressed"] = new PyString(context.SpecialKeyState.ShiftPressed.ToString()); dict["SpecialKeyState"] = specialKeyStateDict; return dict; }
//=================================================================== // 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 }
/// <summary> /// Eval method /// </summary> /// <remarks> /// Evaluate a Python expression and return the result as a PyObject /// or null if an exception is raised. /// </remarks> public PyObject Eval(string code, PyDict locals = null) { Check(); IntPtr _locals = locals == null ? variables : locals.obj; var flag = (IntPtr)Runtime.Py_eval_input; NewReference reference = Runtime.PyRun_String( code, flag, variables, _locals ); try { Runtime.CheckExceptionOccurred(); return(reference.MoveToPyObject()); } finally { reference.Dispose(); } }
/// <summary> /// InvokeMethod Method /// </summary> /// <remarks> /// Invoke the named method of the object with the given arguments /// and keyword arguments. Keyword args are passed as a PyDict object. /// A PythonException is raised if the invocation is unsuccessful. /// </remarks> public PyObject InvokeMethod(string name, PyObject[] args, PyDict kw) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (args == null) { throw new ArgumentNullException(nameof(args)); } if (args.Contains(null)) { throw new ArgumentNullException(); } PyObject method = GetAttr(name); PyObject result = method.Invoke(args, kw); method.Dispose(); return(result); }
/// <summary> /// Invoke Method /// </summary> /// <remarks> /// Invoke the callable object with the given positional and keyword /// arguments. A PythonException is raised if the invocation fails. /// </remarks> public PyObject Invoke(PyObject[] args, PyDict kw) { if (args == null) { throw new ArgumentNullException(nameof(args)); } if (args.Contains(null)) { throw new ArgumentNullException(); } var t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw?.obj ?? IntPtr.Zero); t.Dispose(); if (r == IntPtr.Zero) { throw new PythonException(); } return(new PyObject(r)); }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { serializer.Serialize(writer, null); return; } var jobj = (PyObject)value; var jojb_type = jobj.GetPythonType().ToString(); if (jojb_type == "<class 'NoneType'>") { writer.WriteNull(); } else if (PyDict.IsDictType(jobj)) { var dict = new PyDict(jobj); var keys = dict.Keys(); writer.WriteStartObject(); foreach (PyObject key in keys) { string name = key.ToString(); var val = jobj[key];//.ToString(); writer.WritePropertyName(name); serializer.Serialize(writer, val, null); } writer.WriteEndObject(); } else if (PyLong.IsLongType(jobj)) { var pobj = new PyLong(jobj); writer.WriteValue(pobj.ToInt64()); } else if (PyInt.IsIntType(jobj)) { var pobj = new PyInt(jobj); writer.WriteValue(pobj.ToInt32()); } else if (PyFloat.IsFloatType(jobj)) { var pobj = new PyFloat(jobj); writer.WriteValue(pobj.ToDouble()); } else if (PyString.IsStringType(jobj) || jojb_type == "<class 'datetime.date'>") { // var pobj = new PyString(jobj); writer.WriteValue(jobj.ToString()); } else if (jobj.IsIterable())// && !PyDict.IsDictType(jobj)) { writer.WriteStartArray(); foreach (var element in jobj) { serializer.Serialize(writer, element, null); } writer.WriteEndArray(); } else { var properties = jobj.Dir(); if (properties != null) { writer.WriteStartObject(); foreach (PyObject property in properties) { string name = property.ToString(); if (!property.IsCallable() && !name.StartsWith("__")) { var attr = jobj.GetAttr(property);//.ToString(); writer.WritePropertyName(name); try { serializer.Serialize(writer, attr, null); } catch { writer.WriteNull(); } } } writer.WriteEndObject(); } } }
/// <summary> /// Invoke Method /// </summary> /// /// <remarks> /// Invoke the callable object with the given positional and keyword /// arguments. A PythonException is raised if the invokation fails. /// </remarks> public PyObject Invoke(PyTuple args, PyDict kw) { IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw != null ? kw.obj : IntPtr.Zero); if (r == IntPtr.Zero) { throw new PythonException(); } return new PyObject(r); }
/// <summary> /// InvokeMethod Method /// </summary> /// /// <remarks> /// Invoke the named method of the object with the given arguments /// and keyword arguments. Keyword args are passed as a PyDict object. /// A PythonException is raised if the invokation is unsuccessful. /// </remarks> public PyObject InvokeMethod(string name, PyTuple args, PyDict kw) { PyObject method = GetAttr(name); PyObject result = method.Invoke(args, kw); method.Dispose(); return result; }
private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs) { int arg_count; for (arg_count = 0; arg_count < inargs.Length && !(inargs[arg_count] is Py.KeywordArguments); ++arg_count); IntPtr argtuple = Runtime.PyTuple_New(arg_count); for (int i = 0; i < arg_count; i++) { IntPtr ptr; if (inargs[i] is PyObject) { ptr = ((PyObject)inargs[i]).Handle; Runtime.Incref(ptr); } else { ptr = Converter.ToPython(inargs[i], inargs[i].GetType()); } if (Runtime.PyTuple_SetItem(argtuple, i, ptr) < 0) throw new PythonException(); } args = new PyTuple(argtuple); kwargs = null; for (int i = arg_count; i < inargs.Length; i++) { if (!(inargs[i] is Py.KeywordArguments)) throw new ArgumentException("Keyword arguments must come after normal arguments."); if (kwargs == null) kwargs = (Py.KeywordArguments)inargs[i]; else kwargs.Update((Py.KeywordArguments)inargs[i]); } }
/// <summary> /// Invoke Method /// </summary> /// /// <remarks> /// Invoke the callable object with the given positional and keyword /// arguments. A PythonException is raised if the invokation fails. /// </remarks> public PyObject Invoke(PyObject[] args, PyDict kw) { PyTuple t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw != null ? kw.obj : IntPtr.Zero); t.Dispose(); if (r == IntPtr.Zero) { throw new PythonException(); } return new PyObject(r); }
//==================================================================== // 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> /// Creates a new managed type derived from a base type with any virtual /// methods overridden to call out to python if the associated python /// object has overridden the method. /// </summary> internal static Type CreateDerivedType(string name, Type baseType, BorrowedReference dictRef, string namespaceStr, string assemblyName, string moduleName = "Python.Runtime.Dynamic.dll") { // TODO: clean up IntPtr py_dict = dictRef.DangerousGetAddress(); if (null != namespaceStr) { name = namespaceStr + "." + name; } if (null == assemblyName) { assemblyName = "Python.Runtime.Dynamic"; } ModuleBuilder moduleBuilder = GetModuleBuilder(assemblyName, moduleName); Type baseClass = baseType; var interfaces = new List <Type> { typeof(IPythonDerivedType) }; // if the base type is an interface then use System.Object as the base class // and add the base type to the list of interfaces this new class will implement. if (baseType.IsInterface) { interfaces.Add(baseType); baseClass = typeof(object); } TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Class, baseClass, interfaces.ToArray()); // add a field for storing the python object pointer // FIXME: fb not used FieldBuilder fb = typeBuilder.DefineField("__pyobj__", typeof(CLRObject), FieldAttributes.Public); // override any constructors ConstructorInfo[] constructors = baseClass.GetConstructors(); foreach (ConstructorInfo ctor in constructors) { AddConstructor(ctor, baseType, typeBuilder); } // Override any properties explicitly overridden in python var pyProperties = new HashSet <string>(); if (py_dict != IntPtr.Zero && Runtime.PyDict_Check(py_dict)) { Runtime.XIncref(py_dict); using (var dict = new PyDict(py_dict)) using (PyObject keys = dict.Keys()) { foreach (PyObject pyKey in keys) { using (PyObject value = dict[pyKey]) { if (value.HasAttr("_clr_property_type_")) { string propertyName = pyKey.ToString(); pyProperties.Add(propertyName); // Add the property to the type AddPythonProperty(propertyName, value, typeBuilder); } } } } } // override any virtual methods not already overridden by the properties above MethodInfo[] methods = baseType.GetMethods(); var virtualMethods = new HashSet <string>(); foreach (MethodInfo method in methods) { if (!method.Attributes.HasFlag(MethodAttributes.Virtual) | method.Attributes.HasFlag(MethodAttributes.Final)) { continue; } // skip if this property has already been overridden if ((method.Name.StartsWith("get_") || method.Name.StartsWith("set_")) && pyProperties.Contains(method.Name.Substring(4))) { continue; } // keep track of the virtual methods redirected to the python instance virtualMethods.Add(method.Name); // override the virtual method to call out to the python method, if there is one. AddVirtualMethod(method, baseType, typeBuilder); } // Add any additional methods and properties explicitly exposed from Python. if (py_dict != IntPtr.Zero && Runtime.PyDict_Check(py_dict)) { Runtime.XIncref(py_dict); using (var dict = new PyDict(py_dict)) using (PyObject keys = dict.Keys()) { foreach (PyObject pyKey in keys) { using (PyObject value = dict[pyKey]) { if (value.HasAttr("_clr_return_type_") && value.HasAttr("_clr_arg_types_")) { string methodName = pyKey.ToString(); // if this method has already been redirected to the python method skip it if (virtualMethods.Contains(methodName)) { continue; } // Add the method to the type AddPythonMethod(methodName, value, typeBuilder); } } } } } // add the destructor so the python object created in the constructor gets destroyed MethodBuilder methodBuilder = typeBuilder.DefineMethod("Finalize", MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(void), Type.EmptyTypes); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("Finalize")); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, baseClass.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance)); il.Emit(OpCodes.Ret); Type type = typeBuilder.CreateType(); // scan the assembly so the newly added class can be imported Assembly assembly = Assembly.GetAssembly(type); AssemblyManager.ScanAssembly(assembly); // FIXME: assemblyBuilder not used AssemblyBuilder assemblyBuilder = assemblyBuilders[assemblyName]; 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); }
/// <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(); } } }
/// <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("_") || key.ToString().Equals("__version__")) { PyObject value = locals[key]; Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle); value.Dispose(); } key.Dispose(); } } finally { locals.Dispose(); } } }
/// <summary> /// Return the clr python module (new reference) /// </summary> public static IntPtr GetCLRModule(IntPtr?fromList = null) { root.InitializePreload(); if (Runtime.IsPython2) { Runtime.XIncref(py_clr_module); return(py_clr_module); } // Python 3 // 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 from list and get them from the root if they're not // already in the module dictionary if (fromList != null && fromList != IntPtr.Zero) { if (Runtime.PyTuple_Check(fromList.GetValueOrDefault())) { Runtime.XIncref(py_mod_dict); using (var mod_dict = new PyDict(py_mod_dict)) { Runtime.XIncref(fromList.GetValueOrDefault()); using (var from = new PyTuple(fromList.GetValueOrDefault())) { 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(py_clr_module); }
/// <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(); } } }