@@ -282,7 +282,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
282282 var pynargs = ( int ) Runtime . PyTuple_Size ( args ) ;
283283 object arg ;
284284 var isGeneric = false ;
285- ArrayList defaultArgList = null ;
286285 if ( info != null )
287286 {
288287 _methods = new MethodBase [ 1 ] ;
@@ -301,180 +300,151 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
301300 isGeneric = true ;
302301 }
303302 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 ;
308305
309- if ( pynargs == clrnargs )
310- {
311- match = true ;
306+ if ( ! MatchArgumentCount ( pynargs , pi , out arrayStart , out defaultArgList ) ) {
307+ continue ;
312308 }
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 ++ )
314313 {
315- match = true ;
316- defaultArgList = new ArrayList ( ) ;
317- for ( var v = pynargs ; v < clrnargs ; v ++ )
314+ IntPtr op ;
315+ if ( paramIndex >= pynargs )
318316 {
319- if ( pi [ v ] . DefaultValue == DBNull . Value )
317+ if ( defaultArgList != null )
320318 {
321- match = false ;
322- }
323- else
324- {
325- defaultArgList . Add ( pi [ v ] . DefaultValue ) ;
319+ margs [ paramIndex ] = defaultArgList [ paramIndex - pynargs ] ;
326320 }
321+
322+ continue ;
327323 }
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- }
336324
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+ }
340335
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 )
342342 {
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 )
345347 {
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+ }
373352
374353
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 )
376363 {
377- var typematch = false ;
378- if ( ( pi [ n ] . ParameterType != typeof ( object ) ) && ( pi [ n ] . ParameterType != clrtype ) )
364+ if ( pytype != pyoptype )
379365 {
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 ;
412367 }
413368 else
414369 {
415370 typematch = true ;
416- clrtype = pi [ n ] . ParameterType ;
371+ clrtype = pi [ paramIndex ] . ParameterType ;
417372 }
418373 }
419- else
374+ if ( ! typematch )
420375 {
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+ }
427384 }
428-
429- if ( ! Converter . ToManaged ( op , clrtype , out arg , false ) )
385+ Runtime . XDecref ( pyoptype ) ;
386+ if ( ! typematch )
430387 {
431- Exceptions . Clear ( ) ;
432388 margs = null ;
433389 break ;
434390 }
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 ;
442391 }
443392 else
444393 {
445- if ( defaultArgList != null )
446- {
447- margs [ n ] = defaultArgList [ n - pynargs ] ;
448- }
394+ typematch = true ;
395+ clrtype = pi [ paramIndex ] . ParameterType ;
449396 }
450397 }
398+ else
399+ {
400+ clrtype = pi [ paramIndex ] . ParameterType ;
401+ }
451402
452- if ( margs == null )
403+ if ( pi [ paramIndex ] . IsOut || clrtype . IsByRef )
453404 {
454- continue ;
405+ outs ++ ;
455406 }
456407
457- object target = null ;
458- if ( ! mi . IsStatic && inst != IntPtr . Zero )
408+ if ( ! Converter . ToManaged ( op , clrtype , out arg , false ) )
459409 {
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 ;
474413 }
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+ }
475422
476- return new Binding ( mi , target , margs , outs ) ;
423+ if ( margs == null )
424+ {
425+ continue ;
477426 }
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 ) ;
478448 }
479449 // We weren't able to find a matching method but at least one
480450 // 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
489459 return null ;
490460 }
491461
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+
492493 internal virtual IntPtr Invoke ( IntPtr inst , IntPtr args , IntPtr kw )
493494 {
494495 return Invoke ( inst , args , kw , null , null ) ;
0 commit comments