@@ -27,6 +27,7 @@ public partial class PyObject : DynamicObject, IDisposable
2727#endif
2828
2929 protected internal IntPtr obj = IntPtr . Zero ;
30+ readonly int run = Runtime . GetRun ( ) ;
3031
3132 public static PyObject None => new PyObject ( new BorrowedReference ( Runtime . PyNone ) ) ;
3233 internal BorrowedReference Reference => new BorrowedReference ( this . obj ) ;
@@ -95,11 +96,15 @@ internal PyObject(in StolenReference reference)
9596 // when the managed wrapper is garbage-collected.
9697 ~ PyObject ( )
9798 {
98- if ( obj == IntPtr . Zero )
99- {
100- return ;
101- }
99+ Debug . Assert ( obj != IntPtr . Zero ) ;
100+
101+ #if TRACE_ALLOC
102+ CheckRun ( ) ;
103+ #endif
104+
102105 Finalizer . Instance . AddFinalizedObject ( ref obj ) ;
106+
107+ Dispose ( false ) ;
103108 }
104109
105110
@@ -167,17 +172,6 @@ public object AsManagedObject(Type t)
167172
168173 internal bool IsDisposed => obj == IntPtr . Zero ;
169174
170- /// <summary>
171- /// Dispose Method
172- /// </summary>
173- /// <remarks>
174- /// The Dispose method provides a way to explicitly release the
175- /// Python object represented by a PyObject instance. It is a good
176- /// idea to call Dispose on PyObjects that wrap resources that are
177- /// limited or need strict lifetime control. Otherwise, references
178- /// to Python objects will not be released until a managed garbage
179- /// collection occurs.
180- /// </remarks>
181175 protected virtual void Dispose ( bool disposing )
182176 {
183177 if ( this . obj == IntPtr . Zero )
@@ -188,6 +182,8 @@ protected virtual void Dispose(bool disposing)
188182 if ( Runtime . Py_IsInitialized ( ) == 0 )
189183 throw new InvalidOperationException ( "Python runtime must be initialized" ) ;
190184
185+ CheckRun ( ) ;
186+
191187 if ( ! Runtime . IsFinalizing )
192188 {
193189 long refcount = Runtime . Refcount ( this . obj ) ;
@@ -221,10 +217,26 @@ protected virtual void Dispose(bool disposing)
221217 this . obj = IntPtr . Zero ;
222218 }
223219
220+ /// <summary>
221+ /// The Dispose method provides a way to explicitly release the
222+ /// Python object represented by a PyObject instance. It is a good
223+ /// idea to call Dispose on PyObjects that wrap resources that are
224+ /// limited or need strict lifetime control. Otherwise, references
225+ /// to Python objects will not be released until a managed garbage
226+ /// collection occurs.
227+ /// </summary>
224228 public void Dispose ( )
225229 {
226- Dispose ( true ) ;
227230 GC . SuppressFinalize ( this ) ;
231+ Dispose ( true ) ;
232+ }
233+
234+ internal void CheckRun ( )
235+ {
236+ if ( run != Runtime . GetRun ( ) )
237+ throw new InvalidOperationException (
238+ "PythonEngine was shut down after this object was created." +
239+ " It is an error to attempt to dispose or to continue using it." ) ;
228240 }
229241
230242 internal BorrowedReference GetPythonTypeReference ( )
0 commit comments