Skip to content

Commit 43de985

Browse files
committed
Merge pull request #343 from filmor/fix-shutdown
Closes #343
2 parents 2d1da5d + af6d37f commit 43de985

File tree

3 files changed

+52
-33
lines changed

3 files changed

+52
-33
lines changed

src/runtime/importhook.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ internal class ImportHook
1616

1717
#if PYTHON3
1818
static IntPtr py_clr_module;
19-
static IntPtr module_def;
19+
static IntPtr module_def = IntPtr.Zero;
20+
21+
internal static void InitializeModuleDef()
22+
{
23+
if (module_def == IntPtr.Zero)
24+
module_def = ModuleDefOffset.AllocModuleDef("clr");
25+
}
2026
#endif
2127

2228
//===================================================================
@@ -44,8 +50,8 @@ internal static void Initialize()
4450
root = new CLRModule();
4551

4652
#if PYTHON3
47-
// create a python module with the same methods as the clr module-like object
48-
module_def = ModuleDefOffset.AllocModuleDef("clr");
53+
// create a python module with the same methods as the clr module-like object
54+
InitializeModuleDef();
4955
py_clr_module = Runtime.PyModule_Create2(module_def, 3);
5056

5157
// both dicts are borrowed references
@@ -70,21 +76,13 @@ internal static void Initialize()
7076

7177
internal static void Shutdown()
7278
{
73-
#if PYTHON3
7479
if (0 != Runtime.Py_IsInitialized()) {
80+
#if PYTHON3
7581
Runtime.XDecref(py_clr_module);
76-
Runtime.XDecref(root.pyHandle);
77-
}
78-
ModuleDefOffset.FreeModuleDef(module_def);
7982
#elif PYTHON2
80-
if (0 != Runtime.Py_IsInitialized())
81-
{
82-
Runtime.XDecref(root.pyHandle);
8383
Runtime.XDecref(root.pyHandle);
84-
}
8584
#endif
86-
if (0 != Runtime.Py_IsInitialized())
87-
{
85+
Runtime.XDecref(root.pyHandle);
8886
Runtime.XDecref(py_import);
8987
}
9088
}

src/runtime/interop.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ public static IntPtr AllocModuleDef(string modulename) {
227227
byte[] ascii = Encoding.ASCII.GetBytes(modulename);
228228
int size = name + ascii.Length + 1;
229229
IntPtr ptr = Marshal.AllocHGlobal(size);
230-
for (int i = 0; i <= m_free; i += IntPtr.Size)
230+
for (int i = 0; i < m_free; i += IntPtr.Size)
231231
Marshal.WriteIntPtr(ptr, i, IntPtr.Zero);
232232
Marshal.Copy(ascii, 0, (IntPtr)(ptr + name), ascii.Length);
233233
Marshal.WriteIntPtr(ptr, m_name, (IntPtr)(ptr + name));

src/runtime/pythonengine.cs

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -411,33 +411,54 @@ public static PyObject ModuleFromString(string name, string code)
411411
/// executing the code string as a PyObject instance, or null if
412412
/// an exception was raised.
413413
/// </remarks>
414-
public static PyObject RunString(string code)
414+
public static PyObject RunString(
415+
string code, IntPtr? globals = null, IntPtr? locals = null
416+
)
415417
{
416-
IntPtr globals = Runtime.PyEval_GetGlobals();
417-
IntPtr locals = Runtime.PyDict_New();
418-
419-
IntPtr builtins = Runtime.PyEval_GetBuiltins();
420-
Runtime.PyDict_SetItemString(locals, "__builtins__", builtins);
418+
bool borrowedGlobals = true;
419+
if (globals == null)
420+
{
421+
globals = Runtime.PyEval_GetGlobals();
422+
if (globals == IntPtr.Zero)
423+
{
424+
globals = Runtime.PyDict_New();
425+
Runtime.PyDict_SetItemString(
426+
globals.Value, "__builtins__",
427+
Runtime.PyEval_GetBuiltins()
428+
);
429+
borrowedGlobals = false;
430+
}
431+
}
421432

422-
IntPtr flag = (IntPtr)257; /* Py_file_input */
423-
IntPtr result = Runtime.PyRun_String(code, flag, globals, locals);
424-
Runtime.XDecref(locals);
425-
if (result == IntPtr.Zero)
433+
bool borrowedLocals = true;
434+
if (locals == null)
426435
{
427-
return null;
436+
locals = Runtime.PyDict_New();
437+
borrowedLocals = false;
428438
}
429-
return new PyObject(result);
430-
}
431439

432-
public static PyObject RunString(string code, IntPtr globals, IntPtr locals)
433-
{
434440
IntPtr flag = (IntPtr)257; /* Py_file_input */
435-
IntPtr result = Runtime.PyRun_String(code, flag, globals, locals);
436-
if (result == IntPtr.Zero)
441+
442+
try
437443
{
438-
return null;
444+
IntPtr result = Runtime.PyRun_String(
445+
code, flag, globals.Value, locals.Value
446+
);
447+
448+
if (Runtime.PyErr_Occurred() != 0)
449+
{
450+
throw new PythonException();
451+
}
452+
453+
return new PyObject(result);
454+
}
455+
finally
456+
{
457+
if (!borrowedLocals)
458+
Runtime.XDecref(locals.Value);
459+
if (!borrowedGlobals)
460+
Runtime.XDecref(globals.Value);
439461
}
440-
return new PyObject(result);
441462
}
442463
}
443464

0 commit comments

Comments
 (0)