@@ -291,7 +291,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
291291 {
292292 _methods = GetMethods ( ) ;
293293 }
294- Type clrtype ;
294+
295295 // TODO: Clean up
296296 foreach ( MethodBase mi in _methods )
297297 {
@@ -303,15 +303,14 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
303303 ArrayList defaultArgList ;
304304 int arrayStart ;
305305
306- if ( ! MatchArgumentCount ( pynargs , pi , out arrayStart , out defaultArgList ) ) {
306+ if ( ! MatchesArgumentCount ( pynargs , pi , out arrayStart , out defaultArgList ) ) {
307307 continue ;
308308 }
309309 var outs = 0 ;
310310 var margs = new object [ pi . Length ] ;
311311
312312 for ( int paramIndex = 0 ; paramIndex < pi . Length ; paramIndex ++ )
313313 {
314- IntPtr op ;
315314 if ( paramIndex >= pynargs )
316315 {
317316 if ( defaultArgList != null )
@@ -322,85 +321,21 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
322321 continue ;
323322 }
324323
325- if ( arrayStart == paramIndex )
326- {
324+ IntPtr op = ( arrayStart == paramIndex )
327325 // map remaining Python arguments to a tuple since
328326 // 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 ) ;
352329
330+ var parameter = pi [ paramIndex ] ;
353331
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 ;
401336 }
402337
403- if ( pi [ paramIndex ] . IsOut || clrtype . IsByRef )
338+ if ( parameter . IsOut || clrtype . IsByRef )
404339 {
405340 outs ++ ;
406341 }
@@ -459,32 +394,104 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
459394 return null ;
460395 }
461396
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 )
463470 {
464471 defaultArgList = null ;
465472 var match = false ;
466473 paramsArrayStart = - 1 ;
467474
468- if ( pynargs == pi . Length )
475+ if ( argumentCount == parameters . Length )
469476 {
470477 match = true ;
471- } else if ( pynargs < pi . Length )
478+ } else if ( argumentCount < parameters . Length )
472479 {
473480 match = true ;
474481 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 ) {
477484 match = false ;
478485 } else {
479- defaultArgList . Add ( pi [ v ] . DefaultValue ) ;
486+ defaultArgList . Add ( parameters [ v ] . DefaultValue ) ;
480487 }
481488 }
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 ) ) )
484491 {
485492 // This is a `foo(params object[] bar)` style method
486493 match = true ;
487- paramsArrayStart = pi . Length - 1 ;
494+ paramsArrayStart = parameters . Length - 1 ;
488495 }
489496
490497 return match ;
0 commit comments