@@ -343,13 +343,9 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
343343 int kwargsMatched ;
344344 int defaultsNeeded ;
345345 bool isOperator = OperatorMethod . IsOperatorMethod ( mi ) ; // e.g. op_Addition is defined for OperableObject
346- if ( ! MatchesArgumentCount ( pynargs , pi , kwargDict , out paramsArray , out defaultArgList , out kwargsMatched , out defaultsNeeded ) )
346+ if ( ! MatchesArgumentCount ( pynargs , pi , kwargDict , isOperator , out paramsArray , out defaultArgList , out kwargsMatched , out defaultsNeeded ) )
347347 {
348- if ( isOperator )
349- {
350- defaultArgList = null ;
351- }
352- else { continue ; }
348+ continue ;
353349 }
354350 var outs = 0 ;
355351 int clrnargs = pi . Length ;
@@ -545,6 +541,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
545541 // After we've obtained the first argument from Python, we need to skip the first argument of the CLR
546542 // because operator method is a bound method in Python
547543 paramIndex ++ ; // Leave the first .NET param as null (margs).
544+ parameter = pi [ paramIndex ] ;
548545 }
549546
550547 bool isOut ;
@@ -672,39 +669,42 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool
672669 /// <summary>
673670 /// Check whether the number of Python and .NET arguments match, and compute additional arg information.
674671 /// </summary>
675- /// <param name="positionalArgumentCount ">Number of positional args passed from Python.</param>
672+ /// <param name="pynargs ">Number of positional args passed from Python.</param>
676673 /// <param name="parameters">Parameters of the specified .NET method.</param>
677674 /// <param name="kwargDict">Keyword args passed from Python.</param>
675+ /// <param name="isOperator">True if the parameters' method is an operator.</param>
678676 /// <param name="paramsArray">True if the final param of the .NET method is an array (`params` keyword).</param>
679677 /// <param name="defaultArgList">List of default values for arguments.</param>
680678 /// <param name="kwargsMatched">Number of kwargs from Python that are also present in the .NET method.</param>
681679 /// <param name="defaultsNeeded">Number of non-null defaultsArgs.</param>
682680 /// <returns></returns>
683- static bool MatchesArgumentCount ( int positionalArgumentCount , ParameterInfo [ ] parameters ,
681+ static bool MatchesArgumentCount ( int pynargs , ParameterInfo [ ] parameters ,
684682 Dictionary < string , IntPtr > kwargDict ,
683+ bool isOperator ,
685684 out bool paramsArray ,
686685 out ArrayList defaultArgList ,
687686 out int kwargsMatched ,
688687 out int defaultsNeeded )
689688 {
690689 defaultArgList = null ;
691690 var match = false ;
692- paramsArray = parameters . Length > 0 ? Attribute . IsDefined ( parameters [ parameters . Length - 1 ] , typeof ( ParamArrayAttribute ) ) : false ;
691+ int clrnargs = parameters . Length ;
692+ paramsArray = clrnargs > 0 ? Attribute . IsDefined ( parameters [ clrnargs - 1 ] , typeof ( ParamArrayAttribute ) ) : false ;
693693 var kwargCount = kwargDict . Count ;
694694 kwargsMatched = 0 ;
695695 defaultsNeeded = 0 ;
696-
697- if ( positionalArgumentCount == parameters . Length && kwargDict . Count == 0 )
696+ if ( pynargs == clrnargs && kwargDict . Count == 0 )
698697 {
699698 match = true ;
700699 }
701- else if ( positionalArgumentCount < parameters . Length && ( ! paramsArray || positionalArgumentCount == parameters . Length - 1 ) )
700+ else if ( pynargs < clrnargs && ( ! paramsArray || pynargs == clrnargs - 1 ) )
702701 {
703702 // every parameter past 'positionalArgumentCount' must have either
704- // a corresponding keyword argument or a default parameter
703+ // a corresponding keyword argument or a default parameter, unless
704+ // the method is an operator or accepts a params array.
705705 match = true ;
706706 defaultArgList = new ArrayList ( ) ;
707- for ( var v = positionalArgumentCount ; v < parameters . Length ; v ++ )
707+ for ( var v = pynargs ; v < clrnargs ; v ++ )
708708 {
709709 if ( kwargDict . ContainsKey ( parameters [ v ] . Name ) )
710710 {
@@ -723,14 +723,19 @@ static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] pa
723723 defaultArgList . Add ( parameters [ v ] . GetDefaultValue ( ) ) ;
724724 defaultsNeeded ++ ;
725725 }
726- else if ( ! paramsArray )
726+ else if ( ! isOperator && ! paramsArray )
727727 {
728728 match = false ;
729729 }
730730 }
731+ if ( isOperator && defaultArgList . Count == 0 )
732+ {
733+ // If no default arguments were provided for an operable object.
734+ defaultArgList = null ;
735+ }
731736 }
732- else if ( positionalArgumentCount > parameters . Length && parameters . Length > 0 &&
733- Attribute . IsDefined ( parameters [ parameters . Length - 1 ] , typeof ( ParamArrayAttribute ) ) )
737+ else if ( pynargs > clrnargs && clrnargs > 0 &&
738+ Attribute . IsDefined ( parameters [ clrnargs - 1 ] , typeof ( ParamArrayAttribute ) ) )
734739 {
735740 // This is a `foo(params object[] bar)` style method
736741 match = true ;
0 commit comments