| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -35,27 +35,6 @@ internal static void ReleaseModuleDef() | |||
| 35 | 35 | } | |
| 36 | 36 | #endif | |
| 37 | 37 | ||
| 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 | - | ||
| 59 | 38 | /// <summary> | |
| 60 | 39 | /// Initialize just the __import__ hook itself. | |
| 61 | 40 | /// </summary> | |
@@ -64,7 +43,7 @@ static void InitImport() | |||
| 64 | 43 | // We replace the built-in Python __import__ with our own: first | |
| 65 | 44 | // look in CLR modules, then if we don't find any call the default | |
| 66 | 45 | // Python __import__. | |
| 67 | - IntPtr builtins = GetNewRefToBuiltins(); | ||
| 46 | + IntPtr builtins = Runtime.GetBuiltins(); | ||
| 68 | 47 | py_import = Runtime.PyObject_GetAttrString(builtins, "__import__"); | |
| 69 | 48 | PythonException.ThrowIfIsNull(py_import); | |
| 70 | 49 | ||
@@ -80,7 +59,7 @@ static void InitImport() | |||
| 80 | 59 | /// </summary> | |
| 81 | 60 | static void RestoreImport() | |
| 82 | 61 | { | |
| 83 | - IntPtr builtins = GetNewRefToBuiltins(); | ||
| 62 | + IntPtr builtins = Runtime.GetBuiltins(); | ||
| 84 | 63 | ||
| 85 | 64 | int res = Runtime.PyObject_SetAttrString(builtins, "__import__", py_import); | |
| 86 | 65 | PythonException.ThrowIfIsNotZero(res); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -169,6 +169,8 @@ public class Runtime | |||
| 169 | 169 | /// </summary> | |
| 170 | 170 | internal static readonly Encoding PyEncoding = _UCS == 2 ? Encoding.Unicode : Encoding.UTF32; | |
| 171 | 171 | ||
| 172 | + private static PyReferenceCollection _pyRefs = new PyReferenceCollection(); | ||
| 173 | + | ||
| 172 | 174 | /// <summary> | |
| 173 | 175 | /// Initialize the runtime... | |
| 174 | 176 | /// </summary> | |
@@ -194,99 +196,116 @@ internal static void Initialize(bool initSigs = false) | |||
| 194 | 196 | TypeManager.Reset(); | |
| 195 | 197 | ||
| 196 | 198 | IntPtr op; | |
| 197 | - IntPtr dict; | ||
| 198 | - if (IsPython3) | ||
| 199 | - { | ||
| 200 | - op = PyImport_ImportModule("builtins"); | ||
| 201 | - dict = PyObject_GetAttrString(op, "__dict__"); | ||
| 202 | - } | ||
| 203 | - else // Python2 | ||
| 204 | 199 | { | |
| 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); | ||
| 207 | 239 | } | |
| 208 | - PyNotImplemented = PyObject_GetAttrString(op, "NotImplemented"); | ||
| 209 | - PyBaseObjectType = PyObject_GetAttrString(op, "object"); | ||
| 210 | - | ||
| 211 | - PyNone = PyObject_GetAttrString(op, "None"); | ||
| 212 | - PyTrue = PyObject_GetAttrString(op, "True"); | ||
| 213 | - PyFalse = PyObject_GetAttrString(op, "False"); | ||
| 214 | - | ||
| 215 | - PyBoolType = PyObject_Type(PyTrue); | ||
| 216 | - PyNoneType = PyObject_Type(PyNone); | ||
| 217 | - PyTypeType = PyObject_Type(PyNoneType); | ||
| 218 | - | ||
| 219 | - op = PyObject_GetAttrString(dict, "keys"); | ||
| 220 | - PyMethodType = PyObject_Type(op); | ||
| 221 | - XDecref(op); | ||
| 222 | - | ||
| 223 | - // For some arcane reason, builtins.__dict__.__setitem__ is *not* | ||
| 224 | - // a wrapper_descriptor, even though dict.__setitem__ is. | ||
| 225 | - // | ||
| 226 | - // object.__init__ seems safe, though. | ||
| 227 | - op = PyObject_GetAttrString(PyBaseObjectType, "__init__"); | ||
| 228 | - PyWrapperDescriptorType = PyObject_Type(op); | ||
| 229 | - XDecref(op); | ||
| 230 | - | ||
| 231 | - #if PYTHON3 | ||
| 232 | - XDecref(dict); | ||
| 233 | - #endif | ||
| 234 | 240 | ||
| 235 | 241 | op = PyString_FromString("string"); | |
| 236 | - PyStringType = PyObject_Type(op); | ||
| 242 | + SetPyMember(ref PyStringType, PyObject_Type(op), | ||
| 243 | + () => PyStringType = IntPtr.Zero); | ||
| 237 | 244 | XDecref(op); | |
| 238 | 245 | ||
| 239 | 246 | op = PyUnicode_FromString("unicode"); | |
| 240 | - PyUnicodeType = PyObject_Type(op); | ||
| 247 | + SetPyMember(ref PyUnicodeType, PyObject_Type(op), | ||
| 248 | + () => PyUnicodeType = IntPtr.Zero); | ||
| 241 | 249 | XDecref(op); | |
| 242 | 250 | ||
| 243 | 251 | #if PYTHON3 | |
| 244 | 252 | op = PyBytes_FromString("bytes"); | |
| 245 | - PyBytesType = PyObject_Type(op); | ||
| 253 | + SetPyMember(ref PyBytesType, PyObject_Type(op), | ||
| 254 | + () => PyBytesType = IntPtr.Zero); | ||
| 246 | 255 | XDecref(op); | |
| 247 | 256 | #endif | |
| 248 | 257 | ||
| 249 | 258 | op = PyTuple_New(0); | |
| 250 | - PyTupleType = PyObject_Type(op); | ||
| 259 | + SetPyMember(ref PyTupleType, PyObject_Type(op), | ||
| 260 | + () => PyTupleType = IntPtr.Zero); | ||
| 251 | 261 | XDecref(op); | |
| 252 | 262 | ||
| 253 | 263 | op = PyList_New(0); | |
| 254 | - PyListType = PyObject_Type(op); | ||
| 264 | + SetPyMember(ref PyListType, PyObject_Type(op), | ||
| 265 | + () => PyListType = IntPtr.Zero); | ||
| 255 | 266 | XDecref(op); | |
| 256 | 267 | ||
| 257 | 268 | op = PyDict_New(); | |
| 258 | - PyDictType = PyObject_Type(op); | ||
| 269 | + SetPyMember(ref PyDictType, PyObject_Type(op), | ||
| 270 | + () => PyDictType = IntPtr.Zero); | ||
| 259 | 271 | XDecref(op); | |
| 260 | 272 | ||
| 261 | 273 | op = PyInt_FromInt32(0); | |
| 262 | - PyIntType = PyObject_Type(op); | ||
| 274 | + SetPyMember(ref PyIntType, PyObject_Type(op), | ||
| 275 | + () => PyIntType = IntPtr.Zero); | ||
| 263 | 276 | XDecref(op); | |
| 264 | 277 | ||
| 265 | 278 | op = PyLong_FromLong(0); | |
| 266 | - PyLongType = PyObject_Type(op); | ||
| 279 | + SetPyMember(ref PyLongType, PyObject_Type(op), | ||
| 280 | + () => PyLongType = IntPtr.Zero); | ||
| 267 | 281 | XDecref(op); | |
| 268 | 282 | ||
| 269 | 283 | op = PyFloat_FromDouble(0); | |
| 270 | - PyFloatType = PyObject_Type(op); | ||
| 284 | + SetPyMember(ref PyFloatType, PyObject_Type(op), | ||
| 285 | + () => PyFloatType = IntPtr.Zero); | ||
| 271 | 286 | XDecref(op); | |
| 272 | 287 | ||
| 273 | - #if PYTHON3 | ||
| 288 | + #if !PYTHON2 | ||
| 274 | 289 | PyClassType = IntPtr.Zero; | |
| 275 | 290 | PyInstanceType = IntPtr.Zero; | |
| 276 | - #elif PYTHON2 | ||
| 277 | - IntPtr s = PyString_FromString("_temp"); | ||
| 278 | - IntPtr d = PyDict_New(); | ||
| 291 | + #else | ||
| 292 | + { | ||
| 293 | + IntPtr s = PyString_FromString("_temp"); | ||
| 294 | + IntPtr d = PyDict_New(); | ||
| 279 | 295 | ||
| 280 | - IntPtr c = PyClass_New(IntPtr.Zero, d, s); | ||
| 281 | - PyClassType = PyObject_Type(c); | ||
| 296 | + IntPtr c = PyClass_New(IntPtr.Zero, d, s); | ||
| 297 | + SetPyMember(ref PyClassType, PyObject_Type(c), | ||
| 298 | + () => PyClassType = IntPtr.Zero); | ||
| 282 | 299 | ||
| 283 | - IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero); | ||
| 284 | - PyInstanceType = PyObject_Type(i); | ||
| 300 | + IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero); | ||
| 301 | + SetPyMember(ref PyInstanceType, PyObject_Type(i), | ||
| 302 | + () => PyInstanceType = IntPtr.Zero); | ||
| 285 | 303 | ||
| 286 | - XDecref(s); | ||
| 287 | - XDecref(i); | ||
| 288 | - XDecref(c); | ||
| 289 | - XDecref(d); | ||
| 304 | + XDecref(s); | ||
| 305 | + XDecref(i); | ||
| 306 | + XDecref(c); | ||
| 307 | + XDecref(d); | ||
| 308 | + } | ||
| 290 | 309 | #endif | |
| 291 | 310 | ||
| 292 | 311 | Error = new IntPtr(-1); | |
@@ -380,6 +399,9 @@ internal static void Shutdown() | |||
| 380 | 399 | Exceptions.Shutdown(); | |
| 381 | 400 | ImportHook.Shutdown(); | |
| 382 | 401 | Finalizer.Shutdown(); | |
| 402 | + // TOOD: PyCLRMetaType's release operation still in #958 | ||
| 403 | + PyCLRMetaType = IntPtr.Zero; | ||
| 404 | + ResetPyMembers(); | ||
| 383 | 405 | Py_Finalize(); | |
| 384 | 406 | } | |
| 385 | 407 | ||
@@ -393,6 +415,19 @@ internal static int AtExit() | |||
| 393 | 415 | return 0; | |
| 394 | 416 | } | |
| 395 | 417 | ||
| 418 | + private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease) | ||
| 419 | + { | ||
| 420 | + // XXX: For current usages, value should not be null. | ||
| 421 | + PythonException.ThrowIfIsNull(value); | ||
| 422 | + obj = value; | ||
| 423 | + _pyRefs.Add(value, onRelease); | ||
| 424 | + } | ||
| 425 | + | ||
| 426 | + private static void ResetPyMembers() | ||
| 427 | + { | ||
| 428 | + _pyRefs.Release(); | ||
| 429 | + } | ||
| 430 | + | ||
| 396 | 431 | internal static IntPtr Py_single_input = (IntPtr)256; | |
| 397 | 432 | internal static IntPtr Py_file_input = (IntPtr)257; | |
| 398 | 433 | internal static IntPtr Py_eval_input = (IntPtr)258; | |
@@ -401,6 +436,7 @@ internal static int AtExit() | |||
| 401 | 436 | internal static IntPtr PyModuleType; | |
| 402 | 437 | internal static IntPtr PyClassType; | |
| 403 | 438 | internal static IntPtr PyInstanceType; | |
| 439 | + internal static IntPtr PySuper_Type; | ||
| 404 | 440 | internal static IntPtr PyCLRMetaType; | |
| 405 | 441 | internal static IntPtr PyMethodType; | |
| 406 | 442 | internal static IntPtr PyWrapperDescriptorType; | |
@@ -963,7 +999,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2) | |||
| 963 | 999 | ||
| 964 | 1000 | internal static long PyObject_Size(IntPtr pointer) | |
| 965 | 1001 | { | |
| 966 | - return (long) _PyObject_Size(pointer); | ||
| 1002 | + return (long)_PyObject_Size(pointer); | ||
| 967 | 1003 | } | |
| 968 | 1004 | ||
| 969 | 1005 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyObject_Size")] | |
@@ -1079,7 +1115,7 @@ internal static bool PyLong_Check(IntPtr ob) | |||
| 1079 | 1115 | ||
| 1080 | 1116 | internal static IntPtr PyLong_FromUnsignedLong(object value) | |
| 1081 | 1117 | { | |
| 1082 | - if(Is32Bit || IsWindows) | ||
| 1118 | + if (Is32Bit || IsWindows) | ||
| 1083 | 1119 | return PyLong_FromUnsignedLong32(Convert.ToUInt32(value)); | |
| 1084 | 1120 | else | |
| 1085 | 1121 | return PyLong_FromUnsignedLong64(Convert.ToUInt64(value)); | |
@@ -1269,7 +1305,7 @@ internal static int PySequence_DelSlice(IntPtr pointer, long i1, long i2) | |||
| 1269 | 1305 | ||
| 1270 | 1306 | internal static long PySequence_Size(IntPtr pointer) | |
| 1271 | 1307 | { | |
| 1272 | - return (long) _PySequence_Size(pointer); | ||
| 1308 | + return (long)_PySequence_Size(pointer); | ||
| 1273 | 1309 | } | |
| 1274 | 1310 | ||
| 1275 | 1311 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")] | |
@@ -1294,7 +1330,7 @@ internal static IntPtr PySequence_Repeat(IntPtr pointer, long count) | |||
| 1294 | 1330 | ||
| 1295 | 1331 | internal static long PySequence_Count(IntPtr pointer, IntPtr value) | |
| 1296 | 1332 | { | |
| 1297 | - return (long) _PySequence_Count(pointer, value); | ||
| 1333 | + return (long)_PySequence_Count(pointer, value); | ||
| 1298 | 1334 | } | |
| 1299 | 1335 | ||
| 1300 | 1336 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Count")] | |
@@ -1337,7 +1373,7 @@ internal static IntPtr PyString_FromString(string value) | |||
| 1337 | 1373 | ||
| 1338 | 1374 | internal static long PyBytes_Size(IntPtr op) | |
| 1339 | 1375 | { | |
| 1340 | - return (long) _PyBytes_Size(op); | ||
| 1376 | + return (long)_PyBytes_Size(op); | ||
| 1341 | 1377 | } | |
| 1342 | 1378 | ||
| 1343 | 1379 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyBytes_Size")] | |
@@ -1568,7 +1604,7 @@ internal static bool PyDict_Check(IntPtr ob) | |||
| 1568 | 1604 | ||
| 1569 | 1605 | internal static long PyDict_Size(IntPtr pointer) | |
| 1570 | 1606 | { | |
| 1571 | - return (long) _PyDict_Size(pointer); | ||
| 1607 | + return (long)_PyDict_Size(pointer); | ||
| 1572 | 1608 | } | |
| 1573 | 1609 | ||
| 1574 | 1610 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyDict_Size")] | |
@@ -1646,7 +1682,7 @@ internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr | |||
| 1646 | 1682 | ||
| 1647 | 1683 | internal static long PyList_Size(IntPtr pointer) | |
| 1648 | 1684 | { | |
| 1649 | - return (long) _PyList_Size(pointer); | ||
| 1685 | + return (long)_PyList_Size(pointer); | ||
| 1650 | 1686 | } | |
| 1651 | 1687 | ||
| 1652 | 1688 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")] | |
@@ -1695,7 +1731,7 @@ internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end) | |||
| 1695 | 1731 | ||
| 1696 | 1732 | internal static long PyTuple_Size(IntPtr pointer) | |
| 1697 | 1733 | { | |
| 1698 | - return (long) _PyTuple_Size(pointer); | ||
| 1734 | + return (long)_PyTuple_Size(pointer); | ||
| 1699 | 1735 | } | |
| 1700 | 1736 | ||
| 1701 | 1737 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyTuple_Size")] | |
@@ -1746,6 +1782,9 @@ internal static bool PyIter_Check(IntPtr pointer) | |||
| 1746 | 1782 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1747 | 1783 | internal static extern IntPtr PyImport_Import(IntPtr name); | |
| 1748 | 1784 | ||
| 1785 | + /// <summary> | ||
| 1786 | + /// Return value: New reference. | ||
| 1787 | + /// </summary> | ||
| 1749 | 1788 | [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] | |
| 1750 | 1789 | internal static extern IntPtr PyImport_ImportModule(string name); | |
| 1751 | 1790 | ||
@@ -1945,5 +1984,39 @@ internal static void SetNoSiteFlag() | |||
| 1945 | 1984 | } | |
| 1946 | 1985 | } | |
| 1947 | 1986 | } | |
| 1987 | + | ||
| 1988 | + /// <summary> | ||
| 1989 | + /// Return value: New reference. | ||
| 1990 | + /// </summary> | ||
| 1991 | + internal static IntPtr GetBuiltins() | ||
| 1992 | + { | ||
| 1993 | + return IsPython3 ? PyImport_ImportModule("builtins") | ||
| 1994 | + : PyImport_ImportModule("__builtin__"); | ||
| 1995 | + } | ||
| 1996 | + } | ||
| 1997 | + | ||
| 1998 | + | ||
| 1999 | + class PyReferenceCollection | ||
| 2000 | + { | ||
| 2001 | + private List<KeyValuePair<IntPtr, Action>> _actions = new List<KeyValuePair<IntPtr, Action>>(); | ||
| 2002 | + | ||
| 2003 | + /// <summary> | ||
| 2004 | + /// Record obj's address to release the obj in the future, | ||
| 2005 | + /// obj must alive before calling Release. | ||
| 2006 | + /// </summary> | ||
| 2007 | + public void Add(IntPtr ob, Action onRelease) | ||
| 2008 | + { | ||
| 2009 | + _actions.Add(new KeyValuePair<IntPtr, Action>(ob, onRelease)); | ||
| 2010 | + } | ||
| 2011 | + | ||
| 2012 | + public void Release() | ||
| 2013 | + { | ||
| 2014 | + foreach (var item in _actions) | ||
| 2015 | + { | ||
| 2016 | + Runtime.XDecref(item.Key); | ||
| 2017 | + item.Value?.Invoke(); | ||
| 2018 | + } | ||
| 2019 | + _actions.Clear(); | ||
| 2020 | + } | ||
| 1948 | 2021 | } | |
| 1949 | 2022 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments