//==================================================================== // Implement explicit overload selection using subscript syntax ([]). //==================================================================== public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) { OverloadMapper self = (OverloadMapper)GetManagedObject(tp); // Note: if the type provides a non-generic method with N args // and a generic method that takes N params, then we always // prefer the non-generic version in doing overload selection. Type[] types = Runtime.PythonArgsToTypeArray(idx); if (types == null) { return Exceptions.RaiseTypeError("type(s) expected"); } MethodInfo mi = MethodBinder.MatchSignature(self.m.info, types); if (mi == null) { string e = "No match found for signature"; return Exceptions.RaiseTypeError(e); } MethodBinding mb = new MethodBinding(self.m, self.target); mb.info = mi; Runtime.Incref(mb.pyHandle); return mb.pyHandle; }
public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) { MethodBinding self = (MethodBinding)GetManagedObject(tp); MethodInfo sig = MethodBinder.MatchByTypeSig(self.m.info, idx); if (sig == null) { return Exceptions.RaiseTypeError( "No match found for signature" ); } MethodBinding mb = new MethodBinding(self.m, self.target); mb.info = sig; Runtime.Incref(mb.pyHandle); return mb.pyHandle; }
//==================================================================== // 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.Incref(mb.pyHandle); return mb.pyHandle; }
/// <summary> /// Implement binding of generic methods using the subscript syntax []. /// </summary> public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) { var 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) { return(Exceptions.RaiseTypeError("No match found for given type params")); } var mb = new MethodBinding(self.m, self.target) { info = mi }; return(mb.pyHandle); }
//==================================================================== // Descriptor __get__ implementation. Accessing a CLR method returns // a "bound" method similar to a Python bound method. //==================================================================== public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { MethodObject self = (MethodObject)GetManagedObject(ds); MethodBinding binding; // If the method is accessed through its type (rather than via // an instance) we return an 'unbound' MethodBinding that will // cached for future accesses through the type. if (ob == IntPtr.Zero) { if (self.unbound == null) { self.unbound = new MethodBinding(self, IntPtr.Zero); } binding = self.unbound; Runtime.Incref(binding.pyHandle);; return binding.pyHandle; } if (Runtime.PyObject_IsInstance(ob, tp) < 1) { return Exceptions.RaiseTypeError("invalid argument"); } binding = new MethodBinding(self, ob); return binding.pyHandle; }
//==================================================================== // Descriptor __get__ implementation. Accessing a CLR method returns // a "bound" method similar to a Python bound method. //==================================================================== public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { MethodObject self = (MethodObject)GetManagedObject(ds); MethodBinding binding; // If the method is accessed through its type (rather than via // an instance) we return an 'unbound' MethodBinding that will // cached for future accesses through the type. if (ob == IntPtr.Zero) { if (self.unbound == null) { self.unbound = new MethodBinding(self, IntPtr.Zero, tp); } binding = self.unbound; Runtime.XIncref(binding.pyHandle); ; return binding.pyHandle; } if (Runtime.PyObject_IsInstance(ob, tp) < 1) { return Exceptions.RaiseTypeError("invalid argument"); } // If the object this descriptor is being called with is a subclass of the type // this descriptor was defined on then it will be because the base class method // is being called via super(Derived, self).method(...). // In which case create a MethodBinding bound to the base class. CLRObject obj = GetManagedObject(ob) as CLRObject; if (obj != null && obj.inst.GetType() != self.type && obj.inst is IPythonDerivedType && self.type.IsAssignableFrom(obj.inst.GetType())) { ClassBase basecls = ClassManager.GetClass(self.type); binding = new MethodBinding(self, ob, basecls.pyHandle); return binding.pyHandle; } binding = new MethodBinding(self, ob, tp); return binding.pyHandle; }
//==================================================================== // 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<T>(int arg1, int arg2, string arg3) if (self.info != null) { if (self.info.IsGenericMethod) { int len = Runtime.PyTuple_Size(args); Type[] sigTp = Runtime.PythonArgsToTypeArray(args, true); if (sigTp != null) { Type[] genericTp = self.info.GetGenericArguments(); MethodInfo betterMatch = MethodBinder.MatchSignatureAndParameters(self.m.info, genericTp, sigTp); if (betterMatch != null) { self.info = betterMatch; } } } } // This supports calling a method 'unbound', passing the instance // as the first argument. Note that this is not supported if any // of the overloads are static since we can't know if the intent // was to call the static method or the unbound instance method. List <IntPtr> disposeList = new List <IntPtr>(); try { IntPtr target = self.target; if ((target == IntPtr.Zero) && (!self.m.IsStatic())) { int len = Runtime.PyTuple_Size(args); if (len < 1) { Exceptions.SetError(Exceptions.TypeError, "not enough arguments"); return(IntPtr.Zero); } target = Runtime.PyTuple_GetItem(args, 0); Runtime.Incref(target); disposeList.Add(target); args = Runtime.PyTuple_GetSlice(args, 1, len); disposeList.Add(args); } // if the class is a IPythonDerivedClass and target is not the same as self.targetType // (eg if calling the base class method) then call the original base class method instead // of the target method. IntPtr superType = IntPtr.Zero; if (Runtime.PyObject_TYPE(target) != self.targetType) { CLRObject inst = CLRObject.GetManagedObject(target) as CLRObject; if (inst != null && (inst.inst as IPythonDerivedType) != null) { ClassBase baseType = GetManagedObject(self.targetType) as ClassBase; if (baseType != null) { string baseMethodName = "_" + baseType.type.Name + "__" + self.m.name; IntPtr baseMethod = Runtime.PyObject_GetAttrString(target, baseMethodName); if (baseMethod != IntPtr.Zero) { MethodBinding baseSelf = GetManagedObject(baseMethod) as MethodBinding; if (baseSelf != null) { self = baseSelf; } Runtime.Decref(baseMethod); } else { Runtime.PyErr_Clear(); } } } } return(self.m.Invoke(target, args, kw, self.info)); } finally { foreach (IntPtr ptr in disposeList) { Runtime.Decref(ptr); } } }