using System;
using System.Reflection;
using System.Collections.Generic;
namespace Python.Runtime
{
//========================================================================
// Implements a Python binding type for CLR methods. These work much like
// standard Python method bindings, but the same type is used to bind
// both static and instance methods.
//========================================================================
internal class MethodBinding : ExtensionType
{
internal MethodInfo info;
internal MethodObject m;
internal IntPtr target;
internal IntPtr targetType;
public MethodBinding(MethodObject m, IntPtr target, IntPtr targetType) : base()
{
Runtime.XIncref(target);
this.target = target;
Runtime.XIncref(targetType);
if (targetType == IntPtr.Zero)
targetType = Runtime.PyObject_Type(target);
this.targetType = targetType;
this.info = null;
this.m = m;
}
public MethodBinding(MethodObject m, IntPtr target) : this(m, target, IntPtr.Zero)
{
}
//====================================================================
// Implement binding of generic methods using the subscript syntax [].
//====================================================================
public static IntPtr mp_subscript(IntPtr tp, IntPtr idx)
{
MethodBinding self = (MethodBinding)GetManagedObject(tp);
Type[] types = Runtime.PythonArgsToTypeArray(idx);
if (types == null)
{
return Exceptions.RaiseTypeError("type(s) expected");
}
MethodInfo mi = MethodBinder.MatchParameters(self.m.info, types);
if (mi == null)
{
string e = "No match found for given type params";
return Exceptions.RaiseTypeError(e);
}
MethodBinding mb = new MethodBinding(self.m, self.target);
mb.info = mi;
Runtime.XIncref(mb.pyHandle);
return mb.pyHandle;
}
//====================================================================
// MethodBinding __getattribute__ implementation.
//====================================================================
public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
{
MethodBinding self = (MethodBinding)GetManagedObject(ob);
if (!Runtime.PyString_Check(key))
{
Exceptions.SetError(Exceptions.TypeError, "string expected");
return IntPtr.Zero;
}
string name = Runtime.GetManagedString(key);
if (name == "__doc__")
{
IntPtr doc = self.m.GetDocString();
Runtime.XIncref(doc);
return doc;
}
// XXX deprecate __overloads__ soon...
if (name == "__overloads__" || name == "Overloads")
{
OverloadMapper om = new OverloadMapper(self.m, self.target);
Runtime.XIncref(om.pyHandle);
return om.pyHandle;
}
return Runtime.PyObject_GenericGetAttr(ob, key);
}
//====================================================================
// MethodBinding __call__ implementation.
//====================================================================
public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw)
{
MethodBinding self = (MethodBinding)GetManagedObject(ob);
// This works around a situation where the wrong generic method is picked,
// for example this method in the tests: string Overloaded