Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit df98205

Browse files
authored
Merge branch 'master' into PR/Codecs
2 parents 4c18a1c + 3b938a5 commit df98205

File tree

2 files changed

+139
-61
lines changed

2 files changed

+139
-61
lines changed

src/runtime/importhook.cs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,6 @@ internal static void ReleaseModuleDef()
3535
}
3636
#endif
3737

38-
/// <summary>
39-
/// Get a <i>New reference</i> to the builtins module.
40-
/// </summary>
41-
static IntPtr GetNewRefToBuiltins()
42-
{
43-
if (Runtime.IsPython3)
44-
{
45-
return Runtime.PyImport_ImportModule("builtins");
46-
}
47-
else
48-
{
49-
// dict is a borrowed ref, no need to decref
50-
IntPtr dict = Runtime.PyImport_GetModuleDict();
51-
52-
// GetItemString is a borrowed ref; incref to get a new ref
53-
IntPtr builtins = Runtime.PyDict_GetItemString(dict, "__builtin__");
54-
Runtime.XIncref(builtins);
55-
return builtins;
56-
}
57-
}
58-
5938
/// <summary>
6039
/// Initialize just the __import__ hook itself.
6140
/// </summary>
@@ -64,7 +43,7 @@ static void InitImport()
6443
// We replace the built-in Python __import__ with our own: first
6544
// look in CLR modules, then if we don't find any call the default
6645
// Python __import__.
67-
IntPtr builtins = GetNewRefToBuiltins();
46+
IntPtr builtins = Runtime.GetBuiltins();
6847
py_import = Runtime.PyObject_GetAttrString(builtins, "__import__");
6948
PythonException.ThrowIfIsNull(py_import);
7049

@@ -80,7 +59,7 @@ static void InitImport()
8059
/// </summary>
8160
static void RestoreImport()
8261
{
83-
IntPtr builtins = GetNewRefToBuiltins();
62+
IntPtr builtins = Runtime.GetBuiltins();
8463

8564
int res = Runtime.PyObject_SetAttrString(builtins, "__import__", py_import);
8665
PythonException.ThrowIfIsNotZero(res);

src/runtime/runtime.cs

Lines changed: 137 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ public class Runtime
169169
/// </summary>
170170
internal static readonly Encoding PyEncoding = _UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
171171

172+
private static PyReferenceCollection _pyRefs = new PyReferenceCollection();
173+
172174
/// <summary>
173175
/// Initialize the runtime...
174176
/// </summary>
@@ -194,16 +196,46 @@ internal static void Initialize(bool initSigs = false)
194196
TypeManager.Reset();
195197

196198
IntPtr op;
197-
IntPtr dict;
198-
if (IsPython3)
199-
{
200-
op = PyImport_ImportModule("builtins");
201-
dict = PyObject_GetAttrString(op, "__dict__");
202-
}
203-
else // Python2
204199
{
205-
dict = PyImport_GetModuleDict();
206-
op = PyDict_GetItemString(dict, "__builtin__");
200+
var builtins = GetBuiltins();
201+
SetPyMember(ref PyNotImplemented, PyObject_GetAttrString(builtins, "NotImplemented"),
202+
() => PyNotImplemented = IntPtr.Zero);
203+
204+
SetPyMember(ref PyBaseObjectType, PyObject_GetAttrString(builtins, "object"),
205+
() => PyBaseObjectType = IntPtr.Zero);
206+
207+
SetPyMember(ref PyNone, PyObject_GetAttrString(builtins, "None"),
208+
() => PyNone = IntPtr.Zero);
209+
SetPyMember(ref PyTrue, PyObject_GetAttrString(builtins, "True"),
210+
() => PyTrue = IntPtr.Zero);
211+
SetPyMember(ref PyFalse, PyObject_GetAttrString(builtins, "False"),
212+
() => PyFalse = IntPtr.Zero);
213+
214+
SetPyMember(ref PyBoolType, PyObject_Type(PyTrue),
215+
() => PyBoolType = IntPtr.Zero);
216+
SetPyMember(ref PyNoneType, PyObject_Type(PyNone),
217+
() => PyNoneType = IntPtr.Zero);
218+
SetPyMember(ref PyTypeType, PyObject_Type(PyNoneType),
219+
() => PyTypeType = IntPtr.Zero);
220+
221+
op = PyObject_GetAttrString(builtins, "len");
222+
SetPyMember(ref PyMethodType, PyObject_Type(op),
223+
() => PyMethodType = IntPtr.Zero);
224+
XDecref(op);
225+
226+
// For some arcane reason, builtins.__dict__.__setitem__ is *not*
227+
// a wrapper_descriptor, even though dict.__setitem__ is.
228+
//
229+
// object.__init__ seems safe, though.
230+
op = PyObject_GetAttrString(PyBaseObjectType, "__init__");
231+
SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op),
232+
() => PyWrapperDescriptorType = IntPtr.Zero);
233+
XDecref(op);
234+
235+
SetPyMember(ref PySuper_Type, PyObject_GetAttrString(builtins, "super"),
236+
() => PySuper_Type = IntPtr.Zero);
237+
238+
XDecref(builtins);
207239
}
208240
PyNotImplemented = PyObject_GetAttrString(op, "NotImplemented");
209241
PyBaseObjectType = PyObject_GetAttrString(op, "object");
@@ -234,60 +266,73 @@ internal static void Initialize(bool initSigs = false)
234266
#endif
235267

236268
op = PyString_FromString("string");
237-
PyStringType = PyObject_Type(op);
269+
SetPyMember(ref PyStringType, PyObject_Type(op),
270+
() => PyStringType = IntPtr.Zero);
238271
XDecref(op);
239272

240273
op = PyUnicode_FromString("unicode");
241-
PyUnicodeType = PyObject_Type(op);
274+
SetPyMember(ref PyUnicodeType, PyObject_Type(op),
275+
() => PyUnicodeType = IntPtr.Zero);
242276
XDecref(op);
243277

244278
#if PYTHON3
245279
op = PyBytes_FromString("bytes");
246-
PyBytesType = PyObject_Type(op);
280+
SetPyMember(ref PyBytesType, PyObject_Type(op),
281+
() => PyBytesType = IntPtr.Zero);
247282
XDecref(op);
248283
#endif
249284

250285
op = PyTuple_New(0);
251-
PyTupleType = PyObject_Type(op);
286+
SetPyMember(ref PyTupleType, PyObject_Type(op),
287+
() => PyTupleType = IntPtr.Zero);
252288
XDecref(op);
253289

254290
op = PyList_New(0);
255-
PyListType = PyObject_Type(op);
291+
SetPyMember(ref PyListType, PyObject_Type(op),
292+
() => PyListType = IntPtr.Zero);
256293
XDecref(op);
257294

258295
op = PyDict_New();
259-
PyDictType = PyObject_Type(op);
296+
SetPyMember(ref PyDictType, PyObject_Type(op),
297+
() => PyDictType = IntPtr.Zero);
260298
XDecref(op);
261299

262300
op = PyInt_FromInt32(0);
263-
PyIntType = PyObject_Type(op);
301+
SetPyMember(ref PyIntType, PyObject_Type(op),
302+
() => PyIntType = IntPtr.Zero);
264303
XDecref(op);
265304

266305
op = PyLong_FromLong(0);
267-
PyLongType = PyObject_Type(op);
306+
SetPyMember(ref PyLongType, PyObject_Type(op),
307+
() => PyLongType = IntPtr.Zero);
268308
XDecref(op);
269309

270310
op = PyFloat_FromDouble(0);
271-
PyFloatType = PyObject_Type(op);
311+
SetPyMember(ref PyFloatType, PyObject_Type(op),
312+
() => PyFloatType = IntPtr.Zero);
272313
XDecref(op);
273314

274-
#if PYTHON3
315+
#if !PYTHON2
275316
PyClassType = IntPtr.Zero;
276317
PyInstanceType = IntPtr.Zero;
277-
#elif PYTHON2
278-
IntPtr s = PyString_FromString("_temp");
279-
IntPtr d = PyDict_New();
318+
#else
319+
{
320+
IntPtr s = PyString_FromString("_temp");
321+
IntPtr d = PyDict_New();
280322

281-
IntPtr c = PyClass_New(IntPtr.Zero, d, s);
282-
PyClassType = PyObject_Type(c);
323+
IntPtr c = PyClass_New(IntPtr.Zero, d, s);
324+
SetPyMember(ref PyClassType, PyObject_Type(c),
325+
() => PyClassType = IntPtr.Zero);
283326

284-
IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero);
285-
PyInstanceType = PyObject_Type(i);
327+
IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero);
328+
SetPyMember(ref PyInstanceType, PyObject_Type(i),
329+
() => PyInstanceType = IntPtr.Zero);
286330

287-
XDecref(s);
288-
XDecref(i);
289-
XDecref(c);
290-
XDecref(d);
331+
XDecref(s);
332+
XDecref(i);
333+
XDecref(c);
334+
XDecref(d);
335+
}
291336
#endif
292337

293338
Error = new IntPtr(-1);
@@ -381,6 +426,9 @@ internal static void Shutdown()
381426
Exceptions.Shutdown();
382427
ImportHook.Shutdown();
383428
Finalizer.Shutdown();
429+
// TOOD: PyCLRMetaType's release operation still in #958
430+
PyCLRMetaType = IntPtr.Zero;
431+
ResetPyMembers();
384432
Py_Finalize();
385433
}
386434

@@ -394,6 +442,19 @@ internal static int AtExit()
394442
return 0;
395443
}
396444

445+
private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease)
446+
{
447+
// XXX: For current usages, value should not be null.
448+
PythonException.ThrowIfIsNull(value);
449+
obj = value;
450+
_pyRefs.Add(value, onRelease);
451+
}
452+
453+
private static void ResetPyMembers()
454+
{
455+
_pyRefs.Release();
456+
}
457+
397458
internal static IntPtr Py_single_input = (IntPtr)256;
398459
internal static IntPtr Py_file_input = (IntPtr)257;
399460
internal static IntPtr Py_eval_input = (IntPtr)258;
@@ -402,6 +463,7 @@ internal static int AtExit()
402463
internal static IntPtr PyModuleType;
403464
internal static IntPtr PyClassType;
404465
internal static IntPtr PyInstanceType;
466+
internal static IntPtr PySuper_Type;
405467
internal static IntPtr PyCLRMetaType;
406468
internal static IntPtr PyMethodType;
407469
internal static IntPtr PyWrapperDescriptorType;
@@ -974,7 +1036,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2)
9741036

9751037
internal static long PyObject_Size(IntPtr pointer)
9761038
{
977-
return (long) _PyObject_Size(pointer);
1039+
return (long)_PyObject_Size(pointer);
9781040
}
9791041

9801042
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyObject_Size")]
@@ -1090,7 +1152,7 @@ internal static bool PyLong_Check(IntPtr ob)
10901152

10911153
internal static IntPtr PyLong_FromUnsignedLong(object value)
10921154
{
1093-
if(Is32Bit || IsWindows)
1155+
if (Is32Bit || IsWindows)
10941156
return PyLong_FromUnsignedLong32(Convert.ToUInt32(value));
10951157
else
10961158
return PyLong_FromUnsignedLong64(Convert.ToUInt64(value));
@@ -1280,7 +1342,7 @@ internal static int PySequence_DelSlice(IntPtr pointer, long i1, long i2)
12801342

12811343
internal static long PySequence_Size(IntPtr pointer)
12821344
{
1283-
return (long) _PySequence_Size(pointer);
1345+
return (long)_PySequence_Size(pointer);
12841346
}
12851347

12861348
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")]
@@ -1305,7 +1367,7 @@ internal static IntPtr PySequence_Repeat(IntPtr pointer, long count)
13051367

13061368
internal static long PySequence_Count(IntPtr pointer, IntPtr value)
13071369
{
1308-
return (long) _PySequence_Count(pointer, value);
1370+
return (long)_PySequence_Count(pointer, value);
13091371
}
13101372

13111373
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Count")]
@@ -1348,7 +1410,7 @@ internal static IntPtr PyString_FromString(string value)
13481410

13491411
internal static long PyBytes_Size(IntPtr op)
13501412
{
1351-
return (long) _PyBytes_Size(op);
1413+
return (long)_PyBytes_Size(op);
13521414
}
13531415

13541416
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyBytes_Size")]
@@ -1579,7 +1641,7 @@ internal static bool PyDict_Check(IntPtr ob)
15791641

15801642
internal static long PyDict_Size(IntPtr pointer)
15811643
{
1582-
return (long) _PyDict_Size(pointer);
1644+
return (long)_PyDict_Size(pointer);
15831645
}
15841646

15851647
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyDict_Size")]
@@ -1657,7 +1719,7 @@ internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr
16571719

16581720
internal static long PyList_Size(IntPtr pointer)
16591721
{
1660-
return (long) _PyList_Size(pointer);
1722+
return (long)_PyList_Size(pointer);
16611723
}
16621724

16631725
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")]
@@ -1706,7 +1768,7 @@ internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end)
17061768

17071769
internal static long PyTuple_Size(IntPtr pointer)
17081770
{
1709-
return (long) _PyTuple_Size(pointer);
1771+
return (long)_PyTuple_Size(pointer);
17101772
}
17111773

17121774
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyTuple_Size")]
@@ -1757,6 +1819,9 @@ internal static bool PyIter_Check(IntPtr pointer)
17571819
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
17581820
internal static extern IntPtr PyImport_Import(IntPtr name);
17591821

1822+
/// <summary>
1823+
/// Return value: New reference.
1824+
/// </summary>
17601825
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
17611826
internal static extern IntPtr PyImport_ImportModule(string name);
17621827

@@ -1956,5 +2021,39 @@ internal static void SetNoSiteFlag()
19562021
}
19572022
}
19582023
}
2024+
2025+
/// <summary>
2026+
/// Return value: New reference.
2027+
/// </summary>
2028+
internal static IntPtr GetBuiltins()
2029+
{
2030+
return IsPython3 ? PyImport_ImportModule("builtins")
2031+
: PyImport_ImportModule("__builtin__");
2032+
}
2033+
}
2034+
2035+
2036+
class PyReferenceCollection
2037+
{
2038+
private List<KeyValuePair<IntPtr, Action>> _actions = new List<KeyValuePair<IntPtr, Action>>();
2039+
2040+
/// <summary>
2041+
/// Record obj's address to release the obj in the future,
2042+
/// obj must alive before calling Release.
2043+
/// </summary>
2044+
public void Add(IntPtr ob, Action onRelease)
2045+
{
2046+
_actions.Add(new KeyValuePair<IntPtr, Action>(ob, onRelease));
2047+
}
2048+
2049+
public void Release()
2050+
{
2051+
foreach (var item in _actions)
2052+
{
2053+
Runtime.XDecref(item.Key);
2054+
item.Value?.Invoke();
2055+
}
2056+
_actions.Clear();
2057+
}
19592058
}
19602059
}

0 commit comments

Comments
 (0)