[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/chid/pythonnet/master/pythonnet/src/runtime/methodbinding.cs [Back]  [Original]

// ==========================================================================
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
// ==========================================================================

using System;
using System.Reflection;

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 {

	MethodInfo info;
	MethodObject m;
	IntPtr target;

	public MethodBinding(MethodObject m, IntPtr target) : base() {
	    Runtime.Incref(target);
	    this.target = target;
	    this.info = null;
	    this.m = m;
	}


 	//====================================================================
 	// Implement explicit overload selection using subscript syntax ([]).
 	//====================================================================
 
	[CallConvCdecl()]
 	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;	    
 	}


	//====================================================================
	// MethodBinding __getattribute__ implementation. 
	//====================================================================

	[CallConvCdecl()]
	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.Incref(doc);
		return doc;
	    }

	    return Runtime.PyObject_GenericGetAttr(ob, key);
	}


	//====================================================================
	// MethodBinding  __call__ implementation.
	//====================================================================

	[CallConvCdecl()]
	public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) {
	    MethodBinding self = (MethodBinding)GetManagedObject(ob);

	    // 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.

	    if ((self.target == IntPtr.Zero) && (!self.m.IsStatic())) {
		if (Runtime.PyTuple_Size(args) < 1) {
		    Exceptions.SetError(Exceptions.TypeError, 
					"not enough arguments"
					);
		    return IntPtr.Zero;
		}
		int len = Runtime.PyTuple_Size(args);
		IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len);
		IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
		Runtime.Incref(inst);
		IntPtr r = self.m.Invoke(inst, uargs, kw, self.info);
		Runtime.Decref(inst);
		Runtime.Decref(uargs);
		return r;
	    }

	    return self.m.Invoke(self.target, args, kw, self.info);
	}


	//====================================================================
	// MethodBinding  __hash__ implementation.
	//====================================================================

	[CallConvCdecl()]
	public static IntPtr tp_hash(IntPtr ob) {
	    MethodBinding self = (MethodBinding)GetManagedObject(ob);
	    long x = 0;
	    long y = 0;

	    if (self.target != IntPtr.Zero) {
		x = Runtime.PyObject_Hash(self.target).ToInt64();
		if (x == -1) {
		    return new IntPtr(-1);
		}
	    }
 
	    y = Runtime.PyObject_Hash(self.m.pyHandle).ToInt64();
	    if (y == -1) {
		return new IntPtr(-1);
	    }

	    x ^= y;

	    if (x == -1) {
		x = -1;
	    }

	    return new IntPtr(x);
	}


	//====================================================================
	// MethodBinding  __repr__ implementation.
	//====================================================================

	[CallConvCdecl()]
	public static IntPtr tp_repr(IntPtr ob) {
	    MethodBinding self = (MethodBinding)GetManagedObject(ob);
	    string type = (self.target == IntPtr.Zero) ? "unbound" : "bound";
	    string s = String.Format("", type, self.m.name);
	    return Runtime.PyString_FromStringAndSize(s, s.Length);
	}

	//====================================================================
	// MethodBinding dealloc implementation.
	//====================================================================

	[CallConvCdecl()]
	public static new void tp_dealloc(IntPtr ob) {
	    MethodBinding self = (MethodBinding)GetManagedObject(ob);
	    Runtime.Decref(self.target);
	    ExtensionType.FinalizeObject(self);
	}

    }


}

Web Proxy Viewer  |  New URL  |  Original Page