Skip to content

Commit a19b51b

Browse files
committed
cleaned up MethodBinder.Bind a bit
1 parent 93a8c83 commit a19b51b

File tree

1 file changed

+136
-135
lines changed

1 file changed

+136
-135
lines changed

src/runtime/methodbinder.cs

+136-135
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)