@@ -29,21 +29,6 @@ public DelegateManager()
29
29
dispatch = basetype . GetMethod ( "Dispatch" ) ;
30
30
}
31
31
32
- /// <summary>
33
- /// Given a true delegate instance, return the PyObject handle of the
34
- /// Python object implementing the delegate (or IntPtr.Zero if the
35
- /// delegate is not implemented in Python code.
36
- /// </summary>
37
- public IntPtr GetPythonHandle ( Delegate d )
38
- {
39
- if ( d ? . Target is Dispatcher )
40
- {
41
- var disp = ( Dispatcher ) d . Target ;
42
- return disp . target ;
43
- }
44
- return IntPtr . Zero ;
45
- }
46
-
47
32
/// <summary>
48
33
/// GetDispatcher is responsible for creating a class that provides
49
34
/// an appropriate managed callback method for a given delegate type.
@@ -224,41 +209,15 @@ A possible alternate strategy would be to create custom subclasses
224
209
225
210
public class Dispatcher
226
211
{
227
- public IntPtr target ;
228
- public Type dtype ;
229
- private bool _disposed = false ;
230
- private bool _finalized = false ;
212
+ readonly PyObject target ;
213
+ readonly Type dtype ;
231
214
232
215
public Dispatcher ( IntPtr target , Type dtype )
233
216
{
234
- Runtime . XIncref ( target ) ;
235
- this . target = target ;
217
+ this . target = new PyObject ( new BorrowedReference ( target ) ) ;
236
218
this . dtype = dtype ;
237
219
}
238
220
239
- ~ Dispatcher ( )
240
- {
241
- if ( _finalized || _disposed )
242
- {
243
- return ;
244
- }
245
- _finalized = true ;
246
- Finalizer . Instance . AddFinalizedObject ( ref target ) ;
247
- }
248
-
249
- public void Dispose ( )
250
- {
251
- if ( _disposed )
252
- {
253
- return ;
254
- }
255
- _disposed = true ;
256
- Runtime . XDecref ( target ) ;
257
- target = IntPtr . Zero ;
258
- dtype = null ;
259
- GC . SuppressFinalize ( this ) ;
260
- }
261
-
262
221
public object Dispatch ( object [ ] args )
263
222
{
264
223
IntPtr gs = PythonEngine . AcquireLock ( ) ;
@@ -280,26 +239,36 @@ private object TrueDispatch(object[] args)
280
239
{
281
240
MethodInfo method = dtype . GetMethod ( "Invoke" ) ;
282
241
ParameterInfo [ ] pi = method . GetParameters ( ) ;
283
- IntPtr pyargs = Runtime . PyTuple_New ( pi . Length ) ;
284
242
Type rtype = method . ReturnType ;
285
243
286
- for ( var i = 0 ; i < pi . Length ; i ++ )
244
+ NewReference op ;
245
+ using ( var pyargs = NewReference . DangerousFromPointer ( Runtime . PyTuple_New ( pi . Length ) ) )
287
246
{
288
- // Here we own the reference to the Python value, and we
289
- // give the ownership to the arg tuple.
290
- IntPtr arg = Converter . ToPython ( args [ i ] , pi [ i ] . ParameterType ) ;
291
- Runtime . PyTuple_SetItem ( pyargs , i , arg ) ;
292
- }
247
+ for ( var i = 0 ; i < pi . Length ; i ++ )
248
+ {
249
+ // Here we own the reference to the Python value, and we
250
+ // give the ownership to the arg tuple.
251
+ var arg = Converter . ToPythonReference ( args [ i ] , pi [ i ] . ParameterType ) ;
252
+ if ( arg . IsNull ( ) )
253
+ {
254
+ throw PythonException . ThrowLastAsClrException ( ) ;
255
+ }
256
+ int res = Runtime . PyTuple_SetItem ( pyargs , i , arg . Steal ( ) ) ;
257
+ if ( res != 0 )
258
+ {
259
+ throw PythonException . ThrowLastAsClrException ( ) ;
260
+ }
261
+ }
293
262
294
- IntPtr op = Runtime . PyObject_Call ( target , pyargs , IntPtr . Zero ) ;
295
- Runtime . XDecref ( pyargs ) ;
263
+ op = Runtime . PyObject_Call ( target . Reference , pyargs , BorrowedReference . Null ) ;
264
+ }
296
265
297
- if ( op == IntPtr . Zero )
266
+ if ( op . IsNull ( ) )
298
267
{
299
268
throw PythonException . ThrowLastAsClrException ( ) ;
300
269
}
301
270
302
- try
271
+ using ( op )
303
272
{
304
273
int byRefCount = pi . Count ( parameterInfo => parameterInfo . ParameterType . IsByRef ) ;
305
274
if ( byRefCount > 0 )
@@ -339,7 +308,7 @@ private object TrueDispatch(object[] args)
339
308
Type t = pi [ i ] . ParameterType ;
340
309
if ( t . IsByRef )
341
310
{
342
- IntPtr item = Runtime . PyTuple_GetItem ( op , index ++ ) ;
311
+ BorrowedReference item = Runtime . PyTuple_GetItem ( op , index ++ ) ;
343
312
if ( ! Converter . ToManaged ( item , t , out object newArg , true ) )
344
313
{
345
314
Exceptions . RaiseTypeError ( $ "The Python function returned a tuple where element { i } was not { t . GetElementType ( ) } (the out parameter type)") ;
@@ -352,7 +321,7 @@ private object TrueDispatch(object[] args)
352
321
{
353
322
return null ;
354
323
}
355
- IntPtr item0 = Runtime . PyTuple_GetItem ( op , 0 ) ;
324
+ BorrowedReference item0 = Runtime . PyTuple_GetItem ( op , 0 ) ;
356
325
if ( ! Converter . ToManaged ( item0 , rtype , out object result0 , true ) )
357
326
{
358
327
Exceptions . RaiseTypeError ( $ "The Python function returned a tuple where element 0 was not { rtype } (the return type)") ;
@@ -397,10 +366,6 @@ private object TrueDispatch(object[] args)
397
366
398
367
return result ;
399
368
}
400
- finally
401
- {
402
- Runtime . XDecref ( op ) ;
403
- }
404
369
}
405
370
}
406
371
}
0 commit comments