diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index bdef98c27..dca5a53b4 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -16,7 +16,13 @@ internal class ImportHook #if PYTHON3 static IntPtr py_clr_module; - static IntPtr module_def; + static IntPtr module_def = IntPtr.Zero; + + internal static void InitializeModuleDef() + { + if (module_def == IntPtr.Zero) + module_def = ModuleDefOffset.AllocModuleDef("clr"); + } #endif //=================================================================== @@ -44,8 +50,8 @@ internal static void Initialize() root = new CLRModule(); #if PYTHON3 - // create a python module with the same methods as the clr module-like object - module_def = ModuleDefOffset.AllocModuleDef("clr"); + // create a python module with the same methods as the clr module-like object + InitializeModuleDef(); py_clr_module = Runtime.PyModule_Create2(module_def, 3); // both dicts are borrowed references @@ -70,21 +76,13 @@ internal static void Initialize() internal static void Shutdown() { -#if PYTHON3 if (0 != Runtime.Py_IsInitialized()) { +#if PYTHON3 Runtime.XDecref(py_clr_module); - Runtime.XDecref(root.pyHandle); - } - ModuleDefOffset.FreeModuleDef(module_def); #elif PYTHON2 - if (0 != Runtime.Py_IsInitialized()) - { - Runtime.XDecref(root.pyHandle); Runtime.XDecref(root.pyHandle); - } #endif - if (0 != Runtime.Py_IsInitialized()) - { + Runtime.XDecref(root.pyHandle); Runtime.XDecref(py_import); } } diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 0657bc3e6..3dc5ad827 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -227,7 +227,7 @@ public static IntPtr AllocModuleDef(string modulename) { byte[] ascii = Encoding.ASCII.GetBytes(modulename); int size = name + ascii.Length + 1; IntPtr ptr = Marshal.AllocHGlobal(size); - for (int i = 0; i <= m_free; i += IntPtr.Size) + for (int i = 0; i < m_free; i += IntPtr.Size) Marshal.WriteIntPtr(ptr, i, IntPtr.Zero); Marshal.Copy(ascii, 0, (IntPtr)(ptr + name), ascii.Length); Marshal.WriteIntPtr(ptr, m_name, (IntPtr)(ptr + name)); diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 4c676d375..c296f1b87 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -411,33 +411,54 @@ public static PyObject ModuleFromString(string name, string code) /// executing the code string as a PyObject instance, or null if /// an exception was raised. /// </remarks> - public static PyObject RunString(string code) + public static PyObject RunString( + string code, IntPtr? globals = null, IntPtr? locals = null + ) { - IntPtr globals = Runtime.PyEval_GetGlobals(); - IntPtr locals = Runtime.PyDict_New(); - - IntPtr builtins = Runtime.PyEval_GetBuiltins(); - Runtime.PyDict_SetItemString(locals, "__builtins__", builtins); + bool borrowedGlobals = true; + if (globals == null) + { + globals = Runtime.PyEval_GetGlobals(); + if (globals == IntPtr.Zero) + { + globals = Runtime.PyDict_New(); + Runtime.PyDict_SetItemString( + globals.Value, "__builtins__", + Runtime.PyEval_GetBuiltins() + ); + borrowedGlobals = false; + } + } - IntPtr flag = (IntPtr)257; /* Py_file_input */ - IntPtr result = Runtime.PyRun_String(code, flag, globals, locals); - Runtime.XDecref(locals); - if (result == IntPtr.Zero) + bool borrowedLocals = true; + if (locals == null) { - return null; + locals = Runtime.PyDict_New(); + borrowedLocals = false; } - return new PyObject(result); - } - public static PyObject RunString(string code, IntPtr globals, IntPtr locals) - { IntPtr flag = (IntPtr)257; /* Py_file_input */ - IntPtr result = Runtime.PyRun_String(code, flag, globals, locals); - if (result == IntPtr.Zero) + + try { - return null; + IntPtr result = Runtime.PyRun_String( + code, flag, globals.Value, locals.Value + ); + + if (Runtime.PyErr_Occurred() != 0) + { + throw new PythonException(); + } + + return new PyObject(result); + } + finally + { + if (!borrowedLocals) + Runtime.XDecref(locals.Value); + if (!borrowedGlobals) + Runtime.XDecref(globals.Value); } - return new PyObject(result); } }