@@ -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,99 +196,94 @@ 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__" ) ;
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" ) ) ;
210202
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" ) ) ;
214204
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" ) ) ;
218208
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 ) ) ;
222212
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 ) ;
230216
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+ }
234229
235230 op = PyString_FromString ( "string" ) ;
236- PyStringType = PyObject_Type ( op ) ;
231+ SetPyMember ( ref PyStringType , PyObject_Type ( op ) ) ;
237232 XDecref ( op ) ;
238233
239234 op = PyUnicode_FromString ( "unicode" ) ;
240- PyUnicodeType = PyObject_Type ( op ) ;
235+ SetPyMember ( ref PyUnicodeType , PyObject_Type ( op ) ) ;
241236 XDecref ( op ) ;
242237
243238#if PYTHON3
244239 op = PyBytes_FromString ( "bytes" ) ;
245- PyBytesType = PyObject_Type ( op ) ;
240+ SetPyMember ( ref PyBytesType , PyObject_Type ( op ) ) ;
246241 XDecref ( op ) ;
247242#endif
248243
249244 op = PyTuple_New ( 0 ) ;
250- PyTupleType = PyObject_Type ( op ) ;
245+ SetPyMember ( ref PyTupleType , PyObject_Type ( op ) ) ;
251246 XDecref ( op ) ;
252247
253248 op = PyList_New ( 0 ) ;
254- PyListType = PyObject_Type ( op ) ;
249+ SetPyMember ( ref PyListType , PyObject_Type ( op ) ) ;
255250 XDecref ( op ) ;
256251
257252 op = PyDict_New ( ) ;
258- PyDictType = PyObject_Type ( op ) ;
253+ SetPyMember ( ref PyDictType , PyObject_Type ( op ) ) ;
259254 XDecref ( op ) ;
260255
261256 op = PyInt_FromInt32 ( 0 ) ;
262- PyIntType = PyObject_Type ( op ) ;
257+ SetPyMember ( ref PyIntType , PyObject_Type ( op ) ) ;
263258 XDecref ( op ) ;
264259
265260 op = PyLong_FromLong ( 0 ) ;
266- PyLongType = PyObject_Type ( op ) ;
261+ SetPyMember ( ref PyLongType , PyObject_Type ( op ) ) ;
267262 XDecref ( op ) ;
268263
269264 op = PyFloat_FromDouble ( 0 ) ;
270- PyFloatType = PyObject_Type ( op ) ;
265+ SetPyMember ( ref PyFloatType , PyObject_Type ( op ) ) ;
271266 XDecref ( op ) ;
272267
273- #if PYTHON3
268+ #if ! PYTHON2
274269 PyClassType = IntPtr . Zero ;
275270 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 ( ) ;
279275
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 ) ) ;
282278
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 ) ) ;
285281
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+ }
290287#endif
291288
292289 Error = new IntPtr ( - 1 ) ;
@@ -380,6 +377,9 @@ internal static void Shutdown()
380377 Exceptions . Shutdown ( ) ;
381378 ImportHook . Shutdown ( ) ;
382379 Finalizer . Shutdown ( ) ;
380+ // TOOD: PyCLRMetaType's release operation still in #958
381+ PyCLRMetaType = IntPtr . Zero ;
382+ ResetPyMembers ( ) ;
383383 Py_Finalize ( ) ;
384384 }
385385
@@ -393,6 +393,19 @@ internal static int AtExit()
393393 return 0 ;
394394 }
395395
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+
396409 internal static IntPtr Py_single_input = ( IntPtr ) 256 ;
397410 internal static IntPtr Py_file_input = ( IntPtr ) 257 ;
398411 internal static IntPtr Py_eval_input = ( IntPtr ) 258 ;
@@ -401,6 +414,7 @@ internal static int AtExit()
401414 internal static IntPtr PyModuleType ;
402415 internal static IntPtr PyClassType ;
403416 internal static IntPtr PyInstanceType ;
417+ internal static IntPtr PySuper_Type ;
404418 internal static IntPtr PyCLRMetaType ;
405419 internal static IntPtr PyMethodType ;
406420 internal static IntPtr PyWrapperDescriptorType ;
@@ -1746,6 +1760,9 @@ internal static bool PyIter_Check(IntPtr pointer)
17461760 [ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl) ]
17471761 internal static extern IntPtr PyImport_Import( IntPtr name) ;
17481762
1763+ /// <summary>
1764+ /// Return value: New reference.
1765+ /// </summary>
17491766 [ DllImport( _PythonDll, CallingConvention = CallingConvention. Cdecl) ]
17501767 internal static extern IntPtr PyImport_ImportModule( string name) ;
17511768
@@ -1945,5 +1962,54 @@ internal static void SetNoSiteFlag()
19451962 }
19461963 }
19471964 }
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+ }
19482014 }
19492015}
0 commit comments