8000 cleaned up MethodBinder.Bind a bit · losttech/pythonnet@ce97c41 · GitHub
[go: up one dir, main page]

Skip to content

Commit ce97c41

Browse files
committed
cleaned up MethodBinder.Bind a bit
1 parent 542105a commit ce97c41

File tree

1 file changed

+136
-135
lines changed

1 file changed

+136
-135
lines changed

src/runtime/methodbinder.cs

Lines changed: 136 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
283283
var pynargs = (int)Runtime.PyTuple_Size(args);
284284
object arg;
285285
var isGeneric = false;
286-
ArrayList defaultArgList = null;
287286
if (info != null)
288287
{
289288
_methods = new MethodBase[1];
@@ -302,180 +301,151 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
302301
isGeneric = true;
303302
}
304303
ParameterInfo[] pi = mi.GetParameters();
305-
var clrnargs = pi.Length;
306-
var match = false;
307-
var arrayStart = -1;
308-
var outs = 0;
304+
ArrayList defaultArgList;
305+
int arrayStart;
309306

310-
if (pynargs == clrnargs)
311-
{
312-
match = true;
307+
if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) {
308+
continue;
313309
}
314-
else if (pynargs < clrnargs)
310+
var outs = 0;
311+
var margs = new object[pi.Length];
312+
313+
for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++)
315314
{
316-
match = true;
317-
defaultArgList = new ArrayList();
318-
for (var v = pynargs; v < clrnargs; v++)
315+
IntPtr op;
316+
if (paramIndex >= pynargs)
319317
{
320-
if (pi[v].DefaultValue == DBNull.Value)
318+
if (defaultArgList != null)
321319
{
322-
match = false;
323-
}
324-
else
325-
{
326-
defaultArgList.Add(pi[v].DefaultValue);
320+
margs[paramIndex] = defaultArgList[paramIndex - pynargs];
327321
}
322+
323+
continue;
328324
}
329-
}
330-
else if (pynargs > clrnargs && clrnargs > 0 &&
331-
Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute)))
332-
{
333-
// This is a `foo(params object[] bar)` style method
334-
match = true;
335-
arrayStart = clrnargs - 1;
336-
}
337325

338-
if (match)
339-
{
340-
var margs = new object[clrnargs];
326+
if (arrayStart == paramIndex)
327+
{
328+
// map remaining Python arguments to a tuple since
329+
// the managed function accepts it - hopefully :]
330+
op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
331+
}
332+
else
333+
{
334+
op = Runtime.PyTuple_GetItem(args, paramIndex);
335+
}
341336

342-
for (int n = 0; n < clrnargs; n++)
337+
// this logic below handles cases when multiple overloading methods
338+
// are ambiguous, hence comparison between Python and CLR types
339+
// is necessary
340+
clrtype = null;
341+
IntPtr pyoptype;
342+
if (_methods.Length > 1)
343343
{
344-
IntPtr op;
345-
if (n < pynargs)
344+
pyoptype = IntPtr.Zero;
345+
pyoptype = Runtime.PyObject_Type(op);
346+
Exceptions.Clear();
347+
if (pyoptype != IntPtr.Zero)
346348
{
347-
if (arrayStart == n)
348-
{
349-
// map remaining Python arguments to a tuple since
350-
// the managed function accepts it - hopefully :]
351-
op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs);
352-
}
353-
else
354-
{
355-
op = Runtime.PyTuple_GetItem(args, n);
356-
}
357-
358-
// this logic below handles cases when multiple overloading methods
359-
// are ambiguous, hence comparison between Python and CLR types
360-
// is necessary
361-
clrtype = null;
362-
IntPtr pyoptype;
363-
if (_methods.Length > 1)
364-
{
365-
pyoptype = IntPtr.Zero;
366-
pyoptype = Runtime.PyObject_Type(op);
367-
Exceptions.Clear();
368-
if (pyoptype != IntPtr.Zero)
369-
{
370-
clrtype = Converter.GetTypeByAlias(pyoptype);
371-
}
372-
Runtime.XDecref(pyoptype);
373-
}
349+
clrtype = Converter.GetTypeByAlias(pyoptype);
350+
}
351+
Runtime.XDecref(pyoptype);
352+
}
374353

375354

376-
if (clrtype != null)
355+
if (clrtype != null)
356+
{
357+
var typematch = false;
358+
if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype))
359+
{
360+
IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType);
361+
pyoptype = Runtime.PyObject_Type(op);
362+
Exceptions.Clear();
363+
if (pyoptype != IntPtr.Zero)
377364
{
378-
var typematch = false;
379-
if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype))
365+
if (pytype != pyoptype)
380366
{
381-
IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType);
382-
pyoptype = Runtime.PyObject_Type(op);
383-
Exceptions.Clear();
384-
if (pyoptype != IntPtr.Zero)
385-
{
386-
if (pytype != pyoptype)
387-
{
388-
typematch = false;
389-
}
390-
else
391-
{
392-
typematch = true;
393-
clrtype = pi[n].ParameterType;
394-
}
395-
}
396-
if (!typematch)
397-
{
398-
// this takes care of enum values
399-
TypeCode argtypecode = Type.GetTypeCode(pi[n].ParameterType);
400-
TypeCode paramtypecode = Type.GetTypeCode(clrtype);
401-
if (argtypecode == paramtypecode)
402-
{
403-
typematch = true;
404-
clrtype = pi[n].ParameterType;
405-
}
406-
}
407-
Runtime.XDecref(pyoptype);
408-
if (!typematch)
409-
{
410-
margs = null;
411-
break;
412< 10BC0 /td>-
}
367+
typematch = false;
413368
}
414369
else
415370
{
416371
typematch = true;
417-
clrtype = pi[n].ParameterType;
372+
clrtype = pi[paramIndex].ParameterType;
418373
}
419374
}
420-
else
375+
if (!typematch)
421376
{
422-
clrtype = pi[n].ParameterType;
423-
}
424-
425-
if (pi[n].IsOut || clrtype.IsByRef)
426-
{
427-
outs++;
377+
// this takes care of enum values
378+
TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType);
379+
TypeCode paramtypecode = Type.GetTypeCode(clrtype);
380+
if (argtypecode == paramtypecode)
381+
{
382+
typematch = true;
383+
clrtype = pi[paramIndex].ParameterType;
384+
}
428385
}
429-
430-
if (!Converter.ToManaged(op, clrtype, out arg, false))
386+
Runtime.XDecref(pyoptype);
387+
if (!typematch)
431388
{
432-
Exceptions.Clear();
433389
margs = null;
434390
break;
435391
}
436-
if (arrayStart == n)
437-
{
438-
// GetSlice() creates a new reference but GetItem()
439-
// returns only a borrow reference.
440-
Runtime.XDecref(op);
441-
}
442-
margs[n] = arg;
443392
}
444393
else
445394
{
446-
if (defaultArgList != null)
447-
{
448-
margs[n] = defaultArgList[n - pynargs];
449-
}
395+
typematch = true;
396+
clrtype = pi[paramIndex].ParameterType;
450397
}
451398
}
399+
else
400+
{
401+
clrtype = pi[paramIndex].ParameterType;
402+
}
452403

453-
if (margs == null)
404+
if (pi[paramIndex].IsOut || clrtype.IsByRef)
454405
{
455-
continue;
406+
outs++;
456407
}
457408

458-
object target = null;
459-
if (!mi.IsStatic && inst != IntPtr.Zero)
409+
if (!Converter.ToManaged(op, clrtype, out arg, false))
460410
{
461-
//CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
462-
// InvalidCastException: Unable to cast object of type
463-
// 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
464-
var co = ManagedType.GetManagedObject(inst) as CLRObject;
465-
466-
// Sanity check: this ensures a graceful exit if someone does
467-
// something intentionally wrong like call a non-static method
468-
// on the class rather than on an instance of the class.
469-
// XXX maybe better to do this before all the other rigmarole.
470-
if (co == null)
471-
{
472-
return null;
473-
}
474-
target = co.inst;
411+
Exceptions.Clear();
412+
margs = null;
413+
break;
475414
}
415+
if (arrayStart == paramIndex)
416+
{
417+
// GetSlice() creates a new reference but GetItem()
418+
// returns only a borrow reference.
419+
Runtime.XDecref(op);
420+
}
421+
margs[paramIndex] = arg;
422+
}
476423

477-
return new Binding(mi, target, margs, outs);
424+
if (margs == null)
425+
{
426+
continue;
478427
}
428+
429+
object target = null;
430+
if (!mi.IsStatic && inst != IntPtr.Zero)
431+
{
432+
//CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
433+
// InvalidCastException: Unable to cast object of type
434+
// 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
435+
var co = ManagedType.GetManagedObject(inst) as CLRObject;
436+
437+
// Sanity check: this ensures a graceful exit if someone does
438+
// something intentionally wrong like call a non-static method
439+
// on the class rather than on an instance of the class.
440+
// XXX maybe better to do this before all the other rigmarole.
441+
if (co == null)
442+
{
443+
return null;
444+
}
445+
target = co.inst;
446+
}
447+
448+
return new Binding(mi, target, margs, outs);
479449
}
480450
// We weren't able to find a matching method but at least one
481451
// is a generic method and info is null. That happens when a generic
@@ -490,6 +460,37 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
490460
return null;
491461
}
492462

463+
static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList)
464+
{
465+
defaultArgList = null;
466+
var match = false;
467+
paramsArrayStart = -1;
468+
469+
if (pynargs == pi.Length)
470+
{
471+
match = true;
472+
} else if (pynargs < pi.Length)
473+
{
474+
match = true;
475+
defaultArgList = new ArrayList();
476+
for (var v = pynargs; v < pi.Length; v++) {
477+
if (pi[v].DefaultValue == DBNull.Value) {
478+
match = false;
479+
} else {
480+
defaultArgList.Add(pi[v].DefaultValue);
481+
}
482+
}
483+
} else if (pynargs > pi.Length && pi.Length > 0 &&
484+
Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute)))
485+
{
486+
// This is a `foo(params object[] bar)` style method
487+
match = true;
488+
paramsArrayStart = pi.Length - 1;
489+
}
490+
491+
return match;
492+
}
493+
493494
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw)
494495
{
495496
return Invoke(inst, args, kw, null, null);

0 commit comments

Comments
 (0)
0