@@ -291,7 +291,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
291
291
{
292
292
_methods = GetMethods ( ) ;
293
293
}
294
- Type clrtype ;
294
+
295
295
// TODO: Clean up
296
296
foreach ( MethodBase mi in _methods )
297
297
{
@@ -303,15 +303,14 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
303
303
ArrayList defaultArgList ;
304
304
int arrayStart ;
305
305
306
- if ( ! MatchArgumentCount ( pynargs , pi , out arrayStart , out defaultArgList ) ) {
306
+ if ( ! MatchesArgumentCount ( pynargs , pi , out arrayStart , out defaultArgList ) ) {
307
307
continue ;
308
308
}
309
309
var outs = 0 ;
310
310
var margs = new object [ pi . Length ] ;
311
311
312
312
for ( int paramIndex = 0 ; paramIndex < pi . Length ; paramIndex ++ )
313
313
{
314
- IntPtr op ;
315
314
if ( paramIndex >= pynargs )
316
315
{
317
316
if ( defaultArgList != null )
@@ -322,85 +321,21 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
322
321
continue ;
323
322
}
324
323
325
- if ( arrayStart == paramIndex )
326
- {
324
+ IntPtr op = ( arrayStart == paramIndex )
327
325
// map remaining Python arguments to a tuple since
328
326
// 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
- }
335
-
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
- {
343
- pyoptype = IntPtr . Zero ;
344
- pyoptype = Runtime . PyObject_Type ( op ) ;
345
- Exceptions . Clear ( ) ;
346
- if ( pyoptype != IntPtr . Zero )
347
- {
348
- clrtype = Converter . GetTypeByAlias ( pyoptype ) ;
349
- }
350
- Runtime . XDecref ( pyoptype ) ;
351
- }
327
+ ? Runtime . PyTuple_GetSlice ( args , arrayStart , pynargs )
328
+ : Runtime . PyTuple_GetItem ( args , paramIndex ) ;
352
329
330
+ var parameter = pi [ paramIndex ] ;
353
331
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 )
363
- {
364
- if ( pytype != pyoptype )
365
- {
366
- typematch = false ;
367
- }
368
- else
369
- {
370
- typematch = true ;
371
- clrtype = pi [ paramIndex ] . ParameterType ;
372
- }
373
- }
374
- if ( ! typematch )
375
- {
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
- }
384
- }
385
- Runtime . XDecref ( pyoptype ) ;
386
- if ( ! typematch )
387
- {
388
- margs = null ;
389
- break ;
390
- }
391
- }
392
- else
393
- {
394
- typematch = true ;
395
- clrtype = pi [ paramIndex ] . ParameterType ;
396
- }
397
- }
398
- else
399
- {
400
- clrtype = pi [ paramIndex ] . ParameterType ;
332
+ var clrtype = TryComputeClrArgumentType ( parameter . ParameterType , op , needsResolution : _methods . Length > 1 ) ;
333
+ if ( clrtype == null ) {
334
+ margs = null ;
335
+ break ;
401
336
}
402
337
403
- if ( pi [ paramIndex ] . IsOut || clrtype . IsByRef )
338
+ if ( parameter . IsOut || clrtype . IsByRef )
404
339
{
405
340
outs ++ ;
406
341
}
@@ -459,32 +394,104 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
459
394
return null ;
460
395
}
461
396
462
- static bool MatchArgumentCount ( int pynargs , ParameterInfo [ ] pi , out int paramsArrayStart , out ArrayList defaultArgList )
397
+ static Type TryComputeClrArgumentType ( Type parameterType , IntPtr argument , bool needsResolution )
398
+ {
399
+ // this logic below handles cases when multiple overloading methods
400
+ // are ambiguous, hence comparison between Python and CLR types
401
+ // is necessary
402
+ Type clrtype = null ;
403
+ IntPtr pyoptype ;
404
+ if ( needsResolution )
405
+ {
406
+ // HACK: each overload should be weighted in some way instead
407
+ pyoptype = Runtime . PyObject_Type ( argument ) ;
408
+ Exceptions . Clear ( ) ;
409
+ if ( pyoptype != IntPtr . Zero )
410
+ {
411
+ clrtype = Converter . GetTypeByAlias ( pyoptype ) ;
412
+ }
413
+ Runtime . XDecref ( pyoptype ) ;
414
+ }
415
+
416
+ if ( clrtype != null )
417
+ {
418
+ var typematch = false ;
419
+ if ( ( parameterType != typeof ( object ) ) && ( parameterType != clrtype ) )
420
+ {
421
+ IntPtr pytype = Converter . GetPythonTypeByAlias ( parameterType ) ;
422
+ pyoptype = Runtime . PyObject_Type ( argument ) ;
423
+ Exceptions . Clear ( ) ;
424
+ if ( pyoptype != IntPtr . Zero )
425
+ {
426
+ if ( pytype != pyoptype )
427
+ {
428
+ typematch = false ;
429
+ }
430
+ else
431
+ {
432
+ typematch = true ;
433
+ clrtype = parameterType ;
434
+ }
435
+ }
436
+ if ( ! typematch )
437
+ {
438
+ // this takes care of enum values
439
+ TypeCode argtypecode = Type . GetTypeCode ( parameterType ) ;
440
+ TypeCode paramtypecode = Type . GetTypeCode ( clrtype ) ;
441
+ if ( argtypecode == paramtypecode )
442
+ {
443
+ typematch = true ;
444
+ clrtype = parameterType ;
445
+ }
446
+ }
447
+ Runtime . XDecref ( pyoptype ) ;
448
+ if ( ! typematch )
449
+ {
450
+ return null ;
451
+ }
452
+ }
453
+ else
454
+ {
455
+ typematch = true ;
456
+ clrtype = parameterType ;
457
+ }
458
+ }
459
+ else
460
+ {
461
+ clrtype = parameterType ;
462
+ }
463
+
464
+ return clrtype ;
465
+ }
466
+
467
+ static bool MatchesArgumentCount ( int argumentCount , ParameterInfo [ ] parameters ,
468
+ out int paramsArrayStart ,
469
+ out ArrayList defaultArgList )
463
470
{
464
471
defaultArgList = null ;
465
472
var match = false ;
466
473
paramsArrayStart = - 1 ;
467
474
468
- if ( pynargs == pi . Length )
475
+ if ( argumentCount == parameters . Length )
469
476
{
470
477
match = true ;
471
- } else if ( pynargs < pi . Length )
478
+ } else if ( argumentCount < parameters . Length )
472
479
{
473
480
match = true ;
474
481
defaultArgList = new ArrayList ( ) ;
475
- for ( var v = pynargs ; v < pi . Length ; v ++ ) {
476
- if ( pi [ v ] . DefaultValue == DBNull . Value ) {
482
+ for ( var v = argumentCount ; v < parameters . Length ; v ++ ) {
483
+ if ( parameters [ v ] . DefaultValue == DBNull . Value ) {
477
484
match = false ;
478
485
} else {
479
- defaultArgList . Add ( pi [ v ] . DefaultValue ) ;
486
+ defaultArgList . Add ( parameters [ v ] . DefaultValue ) ;
480
487
}
481
488
}
482
- } else if ( pynargs > pi . Length && pi . Length > 0 &&
483
- Attribute . IsDefined ( pi [ pi . Length - 1 ] , typeof ( ParamArrayAttribute ) ) )
489
+ } else if ( argumentCount > parameters . Length && parameters . Length > 0 &&
490
+ Attribute . IsDefined ( parameters [ parameters . Length - 1 ] , typeof ( ParamArrayAttribute ) ) )
484
491
{
485
492
// This is a `foo(params object[] bar)` style method
486
493
match = true ;
487
- paramsArrayStart = pi . Length - 1 ;
494
+ paramsArrayStart = parameters . Length - 1 ;
488
495
}
489
496
490
497
return match ;
0 commit comments