@@ -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,94 @@ 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__" ) ;
207
- }
208
- PyNotImplemented = PyObject_GetAttrString ( op , "NotImplemented" ) ;
209
- PyBaseObjectType = PyObject_GetAttrString ( op , "object" ) ;
200
+ var builtins = GetBuiltins ( ) ;
201
+ SetPyMember ( ref PyNotImplemented , PyObject_GetAttrString ( builtins , "NotImplemented" ) ) ;
210
202
211
- PyNone = PyObject_GetAttrString ( op , "None" ) ;
212
- PyTrue = PyObject_GetAttrString ( op , "True" ) ;
213
- PyFalse = PyObject_GetAttrString ( op , "False" ) ;
203
+ SetPyMember ( ref PyBaseObjectType , PyObject_GetAttrString ( builtins , "object" ) ) ;
214
204
215
- PyBoolType = PyObject_Type ( PyTrue ) ;
216
- PyNoneType = PyObject_Type ( PyNone ) ;
217
- PyTypeType = PyObject_Type ( PyNoneType ) ;
205
+ SetPyMember ( ref PyNone , PyObject_GetAttrString ( builtins , "None" ) ) ;
206
+ SetPyMember ( ref PyTrue , PyObject_GetAttrString ( builtins , "True" ) ) ;
207
+ SetPyMember ( ref PyFalse , PyObject_GetAttrString ( builtins , "False" ) ) ;
218
208
219
- op = PyObject_GetAttrString ( dict , "keys" ) ;
220
- PyMethodType = PyObject_Type ( op ) ;
221
- XDecref ( op ) ;
209
+ SetPyMember ( ref PyBoolType , PyObject_Type ( PyTrue ) ) ;
210
+ SetPyMember ( ref PyNoneType , PyObject_Type ( PyNone ) ) ;
211
+ SetPyMember ( ref PyTypeType , PyObject_Type ( PyNoneType ) ) ;
222
212
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 ) ;
213
+ op = PyObject_GetAttrString ( builtins , "len" ) ;
214
+ SetPyMember ( ref PyMethodType , PyObject_Type ( op ) ) ;
215
+ XDecref ( op ) ;
230
216
231
- #if PYTHON3
232
- XDecref ( dict ) ;
233
- #endif
217
+ // For some arcane reason, builtins.__dict__.__setitem__ is *not*
218
+ // a wrapper_descriptor, even though dict.__setitem__ is.
219
+ //
220
+ // object.__init__ seems safe, though.
221
+ op = PyObject_GetAttrString ( PyBaseObjectType , "__init__" ) ;
222
+ SetPyMember ( ref PyWrapperDescriptorType , PyObject_Type ( op ) ) ;
223
+ XDecref ( op ) ;
224
+
225
+ SetPyMember ( ref PySuper_Type , PyObject_GetAttrString ( builtins , "super" ) ) ;
226
+
227
+ XDecref ( builtins ) ;
228
+ }
234
229
235
230
op = PyString_FromString ( "string" ) ;
236
- PyStringType = PyObject_Type ( op ) ;
231
+ SetPyMember ( ref PyStringType , PyObject_Type ( op ) ) ;
237
232
XDecref ( op ) ;
238
233
239
234
op = PyUnicode_FromString ( "unicode" ) ;
240
- PyUnicodeType = PyObject_Type ( op ) ;
235
+ SetPyMember ( ref PyUnicodeType , PyObject_Type ( op ) ) ;
241
236
XDecref ( op ) ;
242
237
243
238
#if PYTHON3
244
239
op = PyBytes_FromString ( "bytes" ) ;
245
- PyBytesType = PyObject_Type ( op ) ;
240
+ SetPyMember ( ref PyBytesType , PyObject_Type ( op ) ) ;
246
241
XDecref ( op ) ;
247
242
#endif
248
243
249
244
op = PyTuple_New ( 0 ) ;
250
- PyTupleType = PyObject_Type ( op ) ;
245
+ SetPyMember ( ref PyTupleType , PyObject_Type ( op ) ) ;
251
246
XDecref ( op ) ;
252
247
253
248
op = PyList_New ( 0 ) ;
254
- PyListType = PyObject_Type ( op ) ;
249
+ SetPyMember ( ref PyListType , PyObject_Type ( op ) ) ;
255
250
XDecref ( op ) ;
256
251
257
252
op = PyDict_New ( ) ;
258
- PyDictType = PyObject_Type ( op ) ;
253
+ SetPyMember ( ref PyDictType , PyObject_Type ( op ) ) ;
259
254
XDecref ( op ) ;
260
255
261
256
op = PyInt_FromInt32 ( 0 ) ;
262
- PyIntType = PyObject_Type ( op ) ;
257
+ SetPyMember ( ref PyIntType , PyObject_Type ( op ) ) ;
263
258
XDecref ( op ) ;
264
259
265
260
op = PyLong_FromLong ( 0 ) ;
266
- PyLongType = PyObject_Type ( op ) ;
261
+ SetPyMember ( ref PyLongType , PyObject_Type ( op ) ) ;
267
262
XDecref ( op ) ;
268
263
269
264
op = PyFloat_FromDouble ( 0 ) ;
270
- PyFloatType = PyObject_Type ( op ) ;
265
+ SetPyMember ( ref PyFloatType , PyObject_Type ( op ) ) ;
271
266
XDecref ( op ) ;
272
267
273
- #if PYTHON3
268
+ #if ! PYTHON2
274
269
PyClassType = IntPtr . Zero ;
275
270
PyInstanceType = IntPtr . Zero ;
276
- #elif PYTHON2
277
- IntPtr s = PyString_FromString ( "_temp" ) ;
278
- IntPtr d = PyDict_New ( ) ;
271
+ #else
272
+ {
273
+ IntPtr s = PyString_FromString ( "_temp" ) ;
274
+ IntPtr d = PyDict_New ( ) ;
279
275
280
- IntPtr c = PyClass_New ( IntPtr . Zero , d , s ) ;
281
- PyClassType = PyObject_Type ( c ) ;
276
+ IntPtr c = PyClass_New ( IntPtr . Zero , d , s ) ;
277
+ SetPyMember ( ref PyClassType , PyObject_Type ( c ) ) ;
282
278
283
- IntPtr i = PyInstance_New ( c , IntPtr . Zero , IntPtr . Zero ) ;
284
- PyInstanceType = PyObject_Type ( i ) ;
279
+ IntPtr i = PyInstance_New ( c , IntPtr . Zero , IntPtr . Zero ) ;
280
+ SetPyMember ( ref PyInstanceType , PyObject_Type ( i ) ) ;
285
281
286
- XDecref ( s ) ;
287
- XDecref ( i ) ;
288
- XDecref ( c ) ;
289
- XDecref ( d ) ;
282
+ XDecref ( s ) ;
283
+ XDecref ( i ) ;
284
+ XDecref ( c ) ;
285
+ XDecref ( d ) ;
286
+ }
290
287
#endif
291
288
292
289
Error = new IntPtr ( - 1 ) ;
@@ -380,6 +377,9 @@ internal static void Shutdown()
380
377
Exceptions . Shutdown ( ) ;
381
378
ImportHook . Shutdown ( ) ;
382
379
Finalizer . Shutdown ( ) ;
380
+ // TOOD: PyCLRMetaType's release operation still in #958
381
+ PyCLRMetaType = IntPtr . Zero ;
382
+ ResetPyMembers ( ) ;
383
383
Py_Finalize ( ) ;
384
384
}
385
385
@@ -393,6 +393,19 @@ internal static int AtExit()
393
393
return 0 ;
394
394
}
395
395
396
+ private static void SetPyMember ( ref IntPtr obj , IntPtr value )
397
+ {
398
+ // XXX: For current usages, value should not be null.
399
+ PythonException . ThrowIfIsNull ( value ) ;
400
+ obj = value ;
401
+ _pyRefs . Add ( ref obj ) ;
402
+ }
403
+
404
+ private static void ResetPyMembers ( )
405
+ {
406
+ _pyRefs . Release ( ) ;
407
+ }
408
+
396
409
internal static IntPtr Py_single_input = ( IntPtr ) 256 ;
397
410
internal static IntPtr Py_file_input = ( IntPtr ) 257 ;
398
411
internal static IntPtr Py_eval_input = ( IntPtr ) 258 ;
@@ -401,6 +414,7 @@ internal static int AtExit()
401
414
internal static IntPtr PyModuleType ;
402
415
internal static IntPtr PyClassType ;
403
416
internal static IntPtr PyInstanceType ;
417
+ internal static IntPtr PySuper_Type ;
404
418
internal static IntPtr PyCLRMetaType ;
405
419
internal static IntPtr PyMethodType ;
406
420
internal static IntPtr PyWrapperDescriptorType ;
@@ -1746,6 +1760,9 @@ internal static bool PyIter_Check(IntPtr pointer)
1746
1760
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl) ]
1747
1761
internal static extern IntPtr PyImport_Import( IntPtr name) ;
1748
1762
1763
+ /// <summary>
1764
+ /// Return value: New reference.
1765
+ /// </summary>
1749
1766
[ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl) ]
1750
1767
internal static extern IntPtr PyImport_ImportModule( string name) ;
1751
1768
@@ -1945,5 +1962,54 @@ internal static void SetNoSiteFlag()
1945
1962
}
1946
1963
}
1947
1964
}
1965
+
1966
+ /// <summary>
1967
+ /// Return value: New reference.
1968
+ /// </summary>
1969
+ internal static IntPtr GetBuiltins( )
1970
+ {
1971
+ return IsPython3 ? PyImport_ImportModule( "builtins")
1972
+ : PyImport_ImportModule( "__builtin__") ;
1973
+ }
1974
+ }
1975
+
1976
+
1977
+ class PyReferenceCollection
1978
+ {
1979
+ public List< IntPtr> _objects { get ; private set ; }
1980
+
1981
+ public PyReferenceCollection( )
1982
+ {
1983
+ _objects = new List< IntPtr> ( ) ;
1984
+ }
1985
+
1986
+ /// <summary>
1987
+ /// Record obj's address to release the obj in the future,
1988
+ /// obj must alive before calling Release.
1989
+ /// </summary>
1990
+ public void Add( ref IntPtr obj)
1991
+ {
1992
+ unsafe
1993
+ {
1994
+ fixed ( void * p = & obj)
1995
+ {
1996
+ _objects. Add( ( IntPtr) p) ;
1997
+ }
1998
+ }
1999
+ }
2000
+
2001
+ public void Release( )
2002
+ {
2003
+ foreach ( var objRef in _objects)
2004
+ {
2005
+ unsafe
2006
+ {
2007
+ var p = ( void * * ) objRef;
2008
+ Runtime. XDecref( ( IntPtr) ( * p) ) ;
2009
+ * p = null ;
2010
+ }
2011
+ }
2012
+ _objects. Clear( ) ;
2013
+ }
1948
2014
}
1949
2015
}
0 commit comments