@@ -283,7 +283,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
283
283
var pynargs = ( int ) Runtime . PyTuple_Size ( args ) ;
284
284
object arg ;
285
285
var isGeneric = false ;
286
- ArrayList defaultArgList = null ;
287
286
if ( info != null )
288
287
{
289
288
_methods = new MethodBase [ 1 ] ;
@@ -302,180 +301,151 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
302
301
isGeneric = true ;
303
302
}
304
303
ParameterInfo [ ] pi = mi . GetParameters ( ) ;
305
- var clrnargs = pi . Length ;
306
- var match = false ;
307
- var arrayStart = - 1 ;
308
- var outs = 0 ;
304
+ ArrayList defaultArgList ;
305
+ int arrayStart ;
309
306
310
- if ( pynargs == clrnargs )
311
- {
312
- match = true ;
307
+ if ( ! MatchArgumentCount ( pynargs , pi , out arrayStart , out defaultArgList ) ) {
308
+ continue ;
313
309
}
314
- else if ( pynargs < clrnargs )
310
+ var outs = 0 ;
311
+ var margs = new object [ pi . Length ] ;
312
+
313
+ for ( int paramIndex = 0 ; paramIndex < pi . Length ; paramIndex ++ )
315
314
{
316
- match = true ;
317
- defaultArgList = new ArrayList ( ) ;
318
- for ( var v = pynargs ; v < clrnargs ; v ++ )
315
+ IntPtr op ;
316
+ if ( paramIndex >= pynargs )
319
317
{
320
- if ( pi [ v ] . DefaultValue == DBNull . Value )
318
+ if ( defaultArgList != null )
321
319
{
322
- match = false ;
323
- }
324
- else
325
- {
326
- defaultArgList . Add ( pi [ v ] . DefaultValue ) ;
320
+ margs [ paramIndex ] = defaultArgList [ paramIndex - pynargs ] ;
327
321
}
322
+
323
+ continue ;
328
324
}
329
- }
330
- else if ( pynargs > clrnargs && clrnargs > 0 &&
331
- Attribute . IsDefined ( pi [ clrnargs - 1 ] , typeof ( ParamArrayAttribute ) ) )
332
- {
333
- // This is a `foo(params object[] bar)` style method
334
- match = true ;
335
- arrayStart = clrnargs - 1 ;
336
- }
337
325
338
- if ( match )
339
- {
340
- var margs = new object [ clrnargs ] ;
326
+ if ( arrayStart == paramIndex )
327
+ {
328
+ // map remaining Python arguments to a tuple since
329
+ // the managed function accepts it - hopefully :]
330
+ op = Runtime . PyTuple_GetSlice ( args , arrayStart , pynargs ) ;
331
+ }
332
+ else
333
+ {
334
+ op = Runtime . PyTuple_GetItem ( args , paramIndex ) ;
335
+ }
341
336
342
- for ( int n = 0 ; n < clrnargs ; n ++ )
337
+ // this logic below handles cases when multiple overloading methods
338
+ // are ambiguous, hence comparison between Python and CLR types
339
+ // is necessary
340
+ clrtype = null ;
341
+ IntPtr pyoptype ;
342
+ if ( _methods . Length > 1 )
343
343
{
344
- IntPtr op ;
345
- if ( n < pynargs )
344
+ pyoptype = IntPtr . Zero ;
345
+ pyoptype = Runtime . PyObject_Type ( op ) ;
346
+ Exceptions . Clear ( ) ;
347
+ if ( pyoptype != IntPtr . Zero )
346
348
{
347
- if ( arrayStart == n )
348
- {
349
- // map remaining Python arguments to a tuple since
350
- // the managed function accepts it - hopefully :]
351
- op = Runtime . PyTuple_GetSlice ( args , arrayStart , pynargs ) ;
352
- }
353
- else
354
- {
355
- op = Runtime . PyTuple_GetItem ( args , n ) ;
356
- }
357
-
358
- // this logic below handles cases when multiple overloading methods
359
- // are ambiguous, hence comparison between Python and CLR types
360
- // is necessary
361
- clrtype = null ;
362
- IntPtr pyoptype ;
363
- if ( _methods . Length > 1 )
364
- {
365
- pyoptype = IntPtr . Zero ;
366
- pyoptype = Runtime . PyObject_Type ( op ) ;
367
- Exceptions . Clear ( ) ;
368
- if ( pyoptype != IntPtr . Zero )
369
- {
370
- clrtype = Converter . GetTypeByAlias ( pyoptype ) ;
371
- }
372
- Runtime . XDecref ( pyoptype ) ;
373
- }
349
+ clrtype = Converter . GetTypeByAlias ( pyoptype ) ;
350
+ }
351
+ Runtime . XDecref ( pyoptype ) ;
352
+ }
374
353
375
354
376
- if ( clrtype != null )
355
+ if ( clrtype != null )
356
+ {
357
+ var typematch = false ;
358
+ if ( ( pi [ paramIndex ] . ParameterType != typeof ( object ) ) && ( pi [ paramIndex ] .ParameterType != clrtype ) )
359
+ {
360
+ IntPtr pytype = Converter . GetPythonTypeByAlias ( pi [ paramIndex ] . ParameterType ) ;
361
+ pyoptype = Runtime . PyObject_Type ( op ) ;
362
+ Exceptions . Clear ( ) ;
363
+ if ( pyoptype != IntPtr . Zero )
377
364
{
378
- var typematch = false ;
379
- if ( ( pi [ n ] . ParameterType != typeof ( object ) ) && ( pi [ n ] . ParameterType != clrtype ) )
365
+ if ( pytype != pyoptype )
380
366
{
381
- IntPtr pytype = Converter . GetPythonTypeByAlias ( pi [ n ] . ParameterType ) ;
382
- pyoptype = Runtime . PyObject_Type ( op ) ;
383
- Exceptions . Clear ( ) ;
384
- if ( pyoptype != IntPtr . Zero )
385
- {
386
- if ( pytype != pyoptype )
387
- {
388
- typematch = false ;
389
- }
390
- else
391
- {
392
- typematch = true ;
393
- clrtype = pi [ n ] . ParameterType ;
394
- }
395
- }
396
- if ( ! typematch )
397
- {
398
- // this takes care of enum values
399
- TypeCode argtypecode = Type . GetTypeCode ( pi [ n ] . ParameterType ) ;
400
- TypeCode paramtypecode = Type . GetTypeCode ( clrtype ) ;
401
- if ( argtypecode == paramtypecode )
402
- {
403
- typematch = true ;
404
- clrtype = pi [ n ] . ParameterType ;
405
- }
406
- }
407
- Runtime . XDecref ( pyoptype ) ;
408
- if ( ! typematch )
409
- {
410
- margs = null ;
411
- break ;
412
<
10BC0
/td>
- }
367
+ typematch = false ;
413
368
}
414
369
else
415
370
{
416
371
typematch = true ;
417
- clrtype = pi [ n ] . ParameterType ;
372
+ clrtype = pi [ paramIndex ] . ParameterType ;
418
373
}
419
374
}
420
- else
375
+ if ( ! typematch )
421
376
{
422
- clrtype = pi [ n ] . ParameterType ;
423
- }
424
-
425
- if ( pi [ n ] . IsOut || clrtype . IsByRef )
426
- {
427
- outs ++ ;
377
+ // this takes care of enum values
378
+ TypeCode argtypecode = Type . GetTypeCode ( pi [ paramIndex ] . ParameterType ) ;
379
+ TypeCode paramtypecode = Type . GetTypeCode ( clrtype ) ;
380
+ if ( argtypecode == paramtypecode )
381
+ {
382
+ typematch = true ;
383
+ clrtype = pi [ paramIndex ] . ParameterType ;
384
+ }
428
385
}
429
-
430
- if ( ! Converter . ToManaged ( op , clrtype , out arg , false ) )
386
+ Runtime . XDecref ( pyoptype ) ;
387
+ if ( ! typematch )
431
388
{
432
- Exceptions . Clear ( ) ;
433
389
margs = null ;
434
390
break ;
435
391
}
436
- if ( arrayStart == n )
437
- {
438
- // GetSlice() creates a new reference but GetItem()
439
- // returns only a borrow reference.
440
- Runtime . XDecref ( op ) ;
441
- }
442
- margs [ n ] = arg ;
443
392
}
444
393
else
445
394
{
446
- if ( defaultArgList != null )
447
- {
448
- margs [ n ] = defaultArgList [ n - pynargs ] ;
449
- }
395
+ typematch = true ;
396
+ clrtype = pi [ paramIndex ] . ParameterType ;
450
397
}
451
398
}
399
+ else
400
+ {
401
+ clrtype = pi [ paramIndex ] . ParameterType ;
402
+ }
452
403
453
- if ( margs == null )
404
+ if ( pi [ paramIndex ] . IsOut || clrtype . IsByRef )
454
405
{
455
- continue ;
406
+ outs ++ ;
456
407
}
457
408
458
- object target = null ;
459
- if ( ! mi . IsStatic && inst != IntPtr . Zero )
409
+ if ( ! Converter . ToManaged ( op , clrtype , out arg , false ) )
460
410
{
461
- //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
462
- // InvalidCastException: Unable to cast object of type
463
- // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
464
- var co = ManagedType . GetManagedObject ( inst ) as CLRObject ;
465
-
466
- // Sanity check: this ensures a graceful exit if someone does
467
- // something intentionally wrong like call a non-static method
468
- // on the class rather than on an instance of the class.
469
- // XXX maybe better to do this before all the other rigmarole.
470
- if ( co == null )
471
- {
472
- return null ;
473
- }
474
- target = co . inst ;
411
+ Exceptions . Clear ( ) ;
412
+ margs = null ;
413
+ break ;
475
414
}
415
+ if ( arrayStart == paramIndex )
416
+ {
417
+ // GetSlice() creates a new reference but GetItem()
418
+ // returns only a borrow reference.
419
+ Runtime . XDecref ( op ) ;
420
+ }
421
+ margs [ paramIndex ] = arg ;
422
+ }
476
423
477
- return new Binding ( mi , target , margs , outs ) ;
424
+ if ( margs == null )
425
+ {
426
+ continue ;
478
427
}
428
+
429
+ object target = null ;
430
+ if ( ! mi . IsStatic && inst != IntPtr . Zero )
431
+ {
432
+ //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
433
+ // InvalidCastException: Unable to cast object of type
434
+ // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
435
+ var co = ManagedType . GetManagedObject ( inst ) as CLRObject ;
436
+
437
+ // Sanity check: this ensures a graceful exit if someone does
438
+ // something intentionally wrong like call a non-static method
439
+ // on the class rather than on an instance of the class.
440
+ // XXX maybe better to do this before all the other rigmarole.
441
+ if ( co == null )
442
+ {
443
+ return null ;
444
+ }
445
+ target = co . inst ;
446
+ }
447
+
448
+ return new Binding ( mi , target , margs , outs ) ;
479
449
}
480
450
// We weren't able to find a matching method but at least one
481
451
// is a generic method and info is null. That happens when a generic
@@ -490,6 +460,37 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
490
460
return null ;
491
461
}
492
462
463
+ static bool MatchArgumentCount ( int pynargs , ParameterInfo [ ] pi , out int paramsArrayStart , out ArrayList defaultArgList )
464
+ {
465
+ defaultArgList = null ;
466
+ var match = false ;
467
+ paramsArrayStart = - 1 ;
468
+
469
+ if ( pynargs == pi . Length )
470
+ {
471
+ match = true ;
472
+ } else if ( pynargs < pi . Length )
473
+ {
474
+ match = true ;
475
+ defaultArgList = new ArrayList ( ) ;
476
+ for ( var v = pynargs ; v < pi . Length ; v ++ ) {
477
+ if ( pi [ v ] . DefaultValue == DBNull . Value ) {
478
+ match = false ;
479
+ } else {
480
+ defaultArgList . Add ( pi [ v ] . DefaultValue ) ;
481
+ }
482
+ }
483
+ } else if ( pynargs > pi . Length && pi . Length > 0 &&
484
+ Attribute . IsDefined ( pi [ pi . Length - 1 ] , typeof ( ParamArrayAttribute ) ) )
485
+ {
486
+ // This is a `foo(params object[] bar)` style method
487
+ match = true ;
488
+ paramsArrayStart = pi . Length - 1 ;
489
+ }
490
+
491
+ return match ;
492
+ }
493
+
493
494
internal virtual IntPtr Invoke ( IntPtr inst , IntPtr args , IntPtr kw )
494
495
{
495
496
return Invoke ( inst , args , kw , null , null ) ;
0 commit comments