@@ -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,16 +196,46 @@ 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
240
PyNotImplemented = PyObject_GetAttrString ( op , "NotImplemented" ) ;
209
241
PyBaseObjectType = PyObject_GetAttrString ( op , "object" ) ;
@@ -234,60 +266,73 @@ internal static void Initialize(bool initSigs = false)
234
266
#endif
235
267
236
268
op = PyString_FromString ( "string" ) ;
237
- PyStringType = PyObject_Type ( op ) ;
269
+ SetPyMember ( ref PyStringType , PyObject_Type ( op ) ,
270
+ ( ) => PyStringType = IntPtr . Zero ) ;
238
271
XDecref ( op ) ;
239
272
240
273
op = PyUnicode_FromString ( "unicode" ) ;
241
- PyUnicodeType = PyObject_Type ( op ) ;
274
+ SetPyMember ( ref PyUnicodeType , PyObject_Type ( op ) ,
275
+ ( ) => PyUnicodeType = IntPtr . Zero ) ;
242
276
XDecref ( op ) ;
243
277
244
278
#if PYTHON3
245
279
op = PyBytes_FromString ( "bytes" ) ;
246
- PyBytesType = PyObject_Type ( op ) ;
280
+ SetPyMember ( ref PyBytesType , PyObject_Type ( op ) ,
281
+ ( ) => PyBytesType = IntPtr . Zero ) ;
247
282
XDecref ( op ) ;
248
283
#endif
249
284
250
285
op = PyTuple_New ( 0 ) ;
251
- PyTupleType = PyObject_Type ( op ) ;
286
+ SetPyMember ( ref PyTupleType , PyObject_Type ( op ) ,
287
+ ( ) => PyTupleType = IntPtr . Zero ) ;
252
288
XDecref ( op ) ;
253
289
254
290
op = PyList_New ( 0 ) ;
255
- PyListType = PyObject_Type ( op ) ;
291
+ SetPyMember ( ref PyListType , PyObject_Type ( op ) ,
292
+ ( ) => PyListType = IntPtr . Zero ) ;
256
293
XDecref ( op ) ;
257
294
258
295
op = PyDict_New ( ) ;
259
- PyDictType = PyObject_Type ( op ) ;
296
+ SetPyMember ( ref PyDictType , PyObject_Type ( op ) ,
297
+ ( ) => PyDictType = IntPtr . Zero ) ;
260
298
XDecref ( op ) ;
261
299
262
300
op = PyInt_FromInt32 ( 0 ) ;
263
- PyIntType = PyObject_Type ( op ) ;
301
+ SetPyMember ( ref PyIntType , PyObject_Type ( op ) ,
302
+ ( ) => PyIntType = IntPtr . Zero ) ;
264
303
XDecref ( op ) ;
265
304
266
305
op = PyLong_FromLong ( 0 ) ;
267
- PyLongType = PyObject_Type ( op ) ;
306
+ SetPyMember ( ref PyLongType , PyObject_Type ( op ) ,
307
+ ( ) => PyLongType = IntPtr . Zero ) ;
268
308
XDecref ( op ) ;
269
309
270
310
op = PyFloat_FromDouble ( 0 ) ;
271
- PyFloatType = PyObject_Type ( op ) ;
311
+ SetPyMember ( ref PyFloatType , PyObject_Type ( op ) ,
312
+ ( ) => PyFloatType = IntPtr . Zero ) ;
272
313
XDecref ( op ) ;
273
314
274
- #if PYTHON3
315
+ #if ! PYTHON2
275
316
PyClassType = IntPtr . Zero ;
276
317
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 ( ) ;
280
322
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 ) ;
283
326
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 ) ;
286
330
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
+ }
291
336
#endif
292
337
293
338
Error = new IntPtr ( - 1 ) ;
@@ -381,6 +426,9 @@ internal static void Shutdown()
381
426
Exceptions . Shutdown ( ) ;
382
427
ImportHook . Shutdown ( ) ;
383
428
Finalizer . Shutdown ( ) ;
429
+ // TOOD: PyCLRMetaType's release operation still in #958
430
+ PyCLRMetaType = IntPtr . Zero ;
431
+ ResetPyMembers ( ) ;
384
432
Py_Finalize ( ) ;
385
433
}
386
434
@@ -394,6 +442,19 @@ internal static int AtExit()
394
442
return 0 ;
395
443
}
396
444
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
+
397
458
internal static IntPtr Py_single_input = ( IntPtr ) 256 ;
398
459
internal static IntPtr Py_file_input = ( IntPtr ) 257 ;
399
460
internal static IntPtr Py_eval_input = ( IntPtr ) 258 ;
@@ -402,6 +463,7 @@ internal static int AtExit()
402
463
internal static IntPtr PyModuleType ;
403
464
internal static IntPtr PyClassType ;
404
465
internal static IntPtr PyInstanceType ;
466
+ internal static IntPtr PySuper_Type ;
405
467
internal static IntPtr PyCLRMetaType ;
406
468
internal static IntPtr PyMethodType ;
407
469
internal static IntPtr PyWrapperDescriptorType ;
@@ -974,7 +1036,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2)
974
1036
975
1037
internal static long PyObject_Size( IntPtr pointer)
976
1038
{
977
- return ( long ) _PyObject_Size( pointer) ;
1039
+ return ( long ) _PyObject_Size( pointer) ;
978
1040
}
979
1041
980
1042
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PyObject_Size") ]
@@ -1090,7 +1152,7 @@ internal static bool PyLong_Check(IntPtr ob)
1090
1152
1091
1153
internal static IntPtr PyLong_FromUnsignedLong( object value)
1092
1154
{
1093
- if ( Is32Bit || IsWindows)
1155
+ if ( Is32Bit || IsWindows)
1094
1156
return PyLong_FromUnsignedLong32( Convert. ToUInt32( value) ) ;
1095
1157
else
1096
1158
return PyLong_FromUnsignedLong64( Convert. ToUInt64( value) ) ;
@@ -1280,7 +1342,7 @@ internal static int PySequence_DelSlice(IntPtr pointer, long i1, long i2)
1280
1342
1281
1343
internal static long PySequence_Size( IntPtr pointer)
1282
1344
{
1283
- return ( long ) _PySequence_Size( pointer) ;
1345
+ return ( long ) _PySequence_Size( pointer) ;
1284
1346
}
1285
1347
1286
1348
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PySequence_Size") ]
@@ -1305,7 +1367,7 @@ internal static IntPtr PySequence_Repeat(IntPtr pointer, long count)
1305
1367
1306
1368
internal static long PySequence_Count( IntPtr pointer, IntPtr value)
1307
1369
{
1308
- return ( long ) _PySequence_Count( pointer, value) ;
1370
+ return ( long ) _PySequence_Count( pointer, value) ;
1309
1371
}
1310
1372
1311
1373
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PySequence_Count") ]
@@ -1348,7 +1410,7 @@ internal static IntPtr PyString_FromString(string value)
1348
1410
1349
1411
internal static long PyBytes_Size( IntPtr op)
1350
1412
{
1351
- return ( long ) _PyBytes_Size( op) ;
1413
+ return ( long ) _PyBytes_Size( op) ;
1352
1414
}
1353
1415
1354
1416
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PyBytes_Size") ]
@@ -1579,7 +1641,7 @@ internal static bool PyDict_Check(IntPtr ob)
1579
1641
1580
1642
internal static long PyDict_Size( IntPtr pointer)
1581
1643
{
1582
- return ( long ) _PyDict_Size( pointer) ;
1644
+ return ( long ) _PyDict_Size( pointer) ;
1583
1645
}
1584
1646
1585
1647
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PyDict_Size") ]
@@ -1657,7 +1719,7 @@ internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr
1657
1719
1658
1720
internal static long PyList_Size( IntPtr pointer)
1659
1721
{
1660
- return ( long ) _PyList_Size( pointer) ;
1722
+ return ( long ) _PyList_Size( pointer) ;
1661
1723
}
1662
1724
1663
1725
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PyList_Size") ]
@@ -1706,7 +1768,7 @@ internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end)
1706
1768
1707
1769
internal static long PyTuple_Size( IntPtr pointer)
1708
1770
{
1709
- return ( long ) _PyTuple_Size( pointer) ;
1771
+ return ( long ) _PyTuple_Size( pointer) ;
1710
1772
}
1711
1773
1712
1774
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl, EntryPoint = "PyTuple_Size") ]
@@ -1757,6 +1819,9 @@ internal static bool PyIter_Check(IntPtr pointer)
1757
1819
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl) ]
1758
1820
internal static extern IntPtr PyImport_Import( IntPtr name) ;
1759
1821
1822
+ /// <summary>
1823
+ /// Return value: New reference.
1824
+ /// </summary>
1760
1825
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl) ]
1761
1826
internal static extern IntPtr PyImport_ImportModule( string name) ;
1762
1827
@@ -1956,5 +2021,39 @@ internal static void SetNoSiteFlag()
1956
2021
}
1957
2022
}
1958
2023
}
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
+ }
1959
2058
}
1960
2059
}
0 commit comments