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