@@ -396,164 +396,73 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
396
396
}
397
397
398
398
399
- for ( int index = 0 ; index < argMatchedMethods . Count ; index ++ )
400
- {
401
- var testMatch = argMatchedMethods [ index ] ;
402
- if ( testMatch . DefaultsNeeded == fewestDefaultsRequired && testMatch . KwargsMatched == bestKwargMatchCount )
403
- {
404
- bestCount ++ ;
405
- if ( bestMatchIndex == - 1 )
406
- bestMatchIndex = index ;
407
- }
408
- }
409
-
410
- if ( bestCount > 1 && fewestDefaultsRequired > 0 )
411
- {
412
- // Best effort for determining method to match on gives multiple possible
413
- // matches and we need at least one default argument - bail from this point
414
- StringBuilder stringBuilder = new StringBuilder ( "Not enough arguments provided to disambiguate the method. Found:" ) ;
415
- foreach ( var matchedMethod in argMatchedMethods )
416
- {
417
- stringBuilder . AppendLine ( ) ;
418
- stringBuilder . Append ( matchedMethod . Method . ToString ( ) ) ;
419
- }
420
- Exceptions . SetError ( Exceptions . TypeError , stringBuilder . ToString ( ) ) ;
421
- return null ;
422
- }
423
-
424
- // If we're here either:
425
- // (a) There is only one best match
426
- // (b) There are multiple best matches but none of them require
427
- // default arguments
428
- // in the case of (a) we're done by default. For (b) regardless of which
429
- // method we choose, all arguments are specified _and_ can be converted
430
- // from python to C# so picking any will suffice
431
- MatchedMethod bestMatch = argMatchedMethods [ bestMatchIndex ] ;
432
- var margs = bestMatch . ManagedArgs ;
433
- var outs = bestMatch . Outs ;
434
- var mi = bestMatch . Method ;
435
-
436
- object target = null ;
437
- if ( ! mi . IsStatic && inst != IntPtr . Zero )
438
- {
439
- //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
440
- // InvalidCastException: Unable to cast object of type
441
- // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
442
- var co = ManagedType . GetManagedObject ( inst ) as CLRObject ;
443
-
444
- // Sanity check: this ensures a graceful exit if someone does
445
- // something intentionally wrong like call a non-static method
446
- // on the class rather than on an instance of the class.
447
- // XXX maybe better to do this before all the other rigmarole.
448
- if ( co == null )
449
- {
450
- Exceptions . SetError ( Exceptions . TypeError , "Invoked a non-static method with an invalid instance" ) ;
451
- return null ;
452
- }
453
- target = co . inst ;
454
- }
455
-
456
- return new Binding ( mi , target , margs , outs ) ;
457
- }
458
- else if ( isGeneric && info == null && methodinfo != null )
459
- {
460
- // We weren't able to find a matching method but at least one
461
- // is a generic method and info is null. That happens when a generic
462
- // method was not called using the [] syntax. Let's introspect the
463
- // type of the arguments and use it to construct the correct method.
464
- Type [ ] types = Runtime . PythonArgsToTypeArray ( args , true ) ;
465
- MethodInfo mi = MatchParameters ( methodinfo , types ) ;
466
- if ( mi != null )
467
- {
468
- return Bind ( inst , args , kw , mi , null ) ;
469
- }
470
- }
471
- if ( mismatchedMethods . Count > 0 )
472
- {
473
- var aggregateException = GetAggregateException ( mismatchedMethods ) ;
474
- Exceptions . SetError ( aggregateException ) ;
475
- }
476
- return null ;
477
- }
478
-
479
- static AggregateException GetAggregateException ( IEnumerable < MismatchedMethod > mismatchedMethods )
480
- {
481
- return new AggregateException ( mismatchedMethods . Select ( m => new ArgumentException ( $ "{ m . Exception . Message } in method { m . Method } ", m . Exception ) ) ) ;
482
- }
483
-
484
- static IntPtr HandleParamsArray ( IntPtr args , int arrayStart , int pyArgCount , out bool isNewReference )
485
- {
486
- isNewReference = false ;
487
- IntPtr op ;
488
- // for a params method, we may have a sequence or single/multiple items
489
- // here we look to see if the item at the paramIndex is there or not
490
- // and then if it is a sequence itself.
491
- if ( ( pyArgCount - arrayStart ) == 1 )
492
- {
493
- // we only have one argument left, so we need to check it
494
- // to see if it is a sequence or a single item
495
- IntPtr item = Runtime . PyTuple_GetItem ( args , arrayStart ) ;
496
- if ( ! Runtime . PyString_Check ( item ) && Runtime . PySequence_Check ( item ) )
497
- {
498
- // it's a sequence (and not a string), so we use it as the op
499
- op = item ;
500
- }
501
- else
502
- {
503
- isNewReference = true ;
504
- op = Runtime . PyTuple_GetSlice ( args , arrayStart , pyArgCount ) ;
505
- }
506
- }
507
- else
508
- {
509
- isNewReference = true ;
510
- op = Runtime . PyTuple_GetSlice ( args , arrayStart , pyArgCount ) ;
511
- }
512
- return op ;
513
- }
514
-
515
- /// <summary>
516
- /// Attempts to convert Python positional argument tuple and keyword argument table
517
- /// into an array of managed objects, that can be passed to a method.
518
- /// If unsuccessful, returns null and may set a Python error.
519
- /// </summary>
520
- /// <param name="pi">Information about expected parameters</param>
521
- /// <param name="paramsArray"><c>true</c>, if the last parameter is a params array.</param>
522
- /// <param name="args">A pointer to the Python argument tuple</param>
523
- /// <param name="pyArgCount">Number of arguments, passed by Python</param>
524
- /// <param name="kwargDict">Dictionary of keyword argument name to python object pointer</param>
525
- /// <param name="defaultArgList">A list of default values for omitted parameters</param>
526
- /// <param name="needsResolution"><c>true</c>, if overloading resolution is required</param>
527
- /// <param name="outs">Returns number of output parameters</param>
528
- /// <returns>If successful, an array of .NET arguments that can be passed to the method. Otherwise null.</returns>
529
- static object [ ] TryConvertArguments ( ParameterInfo [ ] pi , bool paramsArray ,
530
- IntPtr args , int pyArgCount ,
531
- Dictionary < string , IntPtr > kwargDict ,
532
- ArrayList defaultArgList ,
533
- bool needsResolution ,
534
- out int outs ,
535
- out bool usedImplicitConversion )
536
- {
537
- usedImplicitConversion = false ;
538
- outs = 0 ;
539
- var margs = new object [ pi . Length ] ;
540
- int arrayStart = paramsArray ? pi . Length - 1 : - 1 ;
541
-
542
- for ( int paramIndex = 0 ; paramIndex < pi . Length ; paramIndex ++ )
543
- {
544
- var parameter = pi [ paramIndex ] ;
545
- bool hasNamedParam = kwargDict . ContainsKey ( parameter . Name ) ;
546
- bool isNewReference = false ;
547
-
548
- if ( paramIndex >= pyArgCount && ! ( hasNamedParam || ( paramsArray && paramIndex == arrayStart ) ) )
549
- {
550
- if ( defaultArgList != null )
551
- {
552
- margs [ paramIndex ] = defaultArgList [ paramIndex - pyArgCount ] ;
553
- }
554
-
555
- continue ;
556
- }
399
+ if ( clrtype != null )
400
+ {
401
+ var typematch = false ;
402
+ if ( ( pi [ n ] . ParameterType != typeof ( object ) ) && ( pi [ n ] . ParameterType != clrtype ) )
403
+ {
404
+ IntPtr pytype = Converter . GetPythonTypeByAlias ( pi [ n ] . ParameterType ) ;
405
+ pyoptype = Runtime . PyObject_Type ( op ) ;
406
+ Exceptions . Clear ( ) ;
407
+ if ( pyoptype != IntPtr . Zero )
408
+ {
409
+ if ( pytype != pyoptype )
410
+ {
411
+ typematch = false ;
412
+ }
413
+ else
414
+ {
415
+ typematch = true ;
416
+ clrtype = pi [ n ] . ParameterType ;
417
+ }
418
+ }
419
+ if ( ! typematch )
420
+ {
421
+ // this takes care of nullables
422
+ var underlyingType = Nullable . GetUnderlyingType ( pi [ n ] . ParameterType ) ;
423
+ if ( underlyingType == null )
424
+ {
425
+ underlyingType = pi [ n ] . ParameterType ;
426
+ }
427
+ // this takes care of enum values
428
+ TypeCode argtypecode = Type . GetTypeCode ( underlyingType ) ;
429
+ TypeCode paramtypecode = Type . GetTypeCode ( clrtype ) ;
430
+ if ( argtypecode == paramtypecode )
431
+ {
432
+ typematch = true ;
433
+ clrtype = pi [ n ] . ParameterType ;
434
+ }
435
+ // accepts non-decimal numbers in decimal parameters
436
+ if ( underlyingType == typeof ( decimal ) )
437
+ {
438
+ clrtype = pi [ n ] . ParameterType ;
439
+ typematch = Converter . ToManaged ( op , clrtype , out arg , false ) ;
440
+ }
441
+ // this takes care of implicit conversions
442
+ var opImplicit = pi [ n ] . ParameterType . GetMethod ( "op_Implicit" , new [ ] { clrtype } ) ;
443
+ if ( opImplicit != null )
444
+ {
445
+ usedImplicitConversion = typematch = opImplicit . ReturnType == pi [ n ] . ParameterType ;
446
+ clrtype = pi [ n ] . ParameterType ;
447
+ }
448
+ }
449
+ Runtime . XDecref ( pyoptype ) ;
450
+ if ( ! typematch )
451
+ {
452
+ margs = null ;
453
+ break ;
454
+ }
455
+ }
456
+ else
457
+ {
458
+ typematch = true ;
459
+ clrtype = pi [ n ] . ParameterType ;
460
+ }
461
+ }
462
+ else
463
+ {
464
+ clrtype = pi [ n ] . ParameterType ;
465
+ }
557
466
558
467
if ( pi [ n ] . IsOut || clrtype . IsByRef )
559
468
{
0 commit comments