public PyMethod(PyObject self, IPyCallable callable) { this.callable = callable; var asSuper = self as PySuper; if (asSuper != null) { selfHandle = (PyObject)asSuper.__getattribute__("__self__"); } else { selfHandle = self; } __setattr__("__call__", this); }
public static Delegate Create(MethodInfo dotNetMethod, Type delegateType, IPyCallable callable, IInterpreter interpreter, FrameContext contextToUseForCall) { var proxy = new CallableDelegateProxy(callable, interpreter, contextToUseForCall); var dotNetMethodParamInfos = dotNetMethod.GetParameters(); if (dotNetMethodParamInfos.Length > 2) { throw new NotImplementedException("We have only created templates for generic wrappers up to 4 arguments"); } Delegate asDelegate; Type[] delegateArgs; MethodInfo genericWrapper; // An ugly amount of copypasta. If we have a return type, then we need an array one element longer to put in RetVal at the end. // We also need to find the method matching the name of the right return type and accommodate the existing of a return value into // the number of generic parameters required for the right binding. if (dotNetMethod.ReturnType == typeof(void)) { delegateArgs = new Type[dotNetMethodParamInfos.Length]; for (int i = 0; i < dotNetMethodParamInfos.Length; ++i) { delegateArgs[i] = dotNetMethodParamInfos[i].ParameterType; } genericWrapper = typeof(CallableDelegateProxy).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance) .Where(x => x.Name == "GenericWrapperVoid" && x.GetParameters().Length == delegateArgs.Length) .First(); } else { throw new Exception("Attempted to bind a callable to an event that requires a return type. We don't support this type of binding. " + "All our callables have to be async, and that meddles with signature of basic return values. Why are you using an event with " + "a return type anyways?"); } var monomorphizedWrapper = genericWrapper.MakeGenericMethod(delegateArgs); asDelegate = Delegate.CreateDelegate(delegateType, proxy, monomorphizedWrapper); return(asDelegate); }
// [TODO][SYS.SCHEDULE - RETURN TASK] sys.schedule should return the task record or a similar handle that the caller can manage public void schedule(PyModule module, FrameContext context, IPyCallable call, params object[] args) { var callCodeObject = call as CodeObject; // [TODO][SYS.SCHEDULE - RETURN TASK - CODEOBJECT] if (callCodeObject != null) { if (args == null) { scheduler.Schedule(callCodeObject, context); } else { scheduler.Schedule(callCodeObject, context, args); } } // [TODO][SYS.SCHEDULE - RETURN TASK - PYCALLABLE] else { call.Call(scheduler.Interpreter, context, args); } }
public PyTypeObject(string name, IPyCallable __init__) { __dict__ = new Dictionary <string, object>(); Name = name; this.__init__ = __init__; __setattr__("__init__", this.__init__); __setattr__("__call__", this); // DefaultNew doesn't invoking any asynchronous code so we won't pass along its context to the wrapper. Expression <Action <PyTypeObject> > expr = instance => DefaultNew(null); var methodInfo = ((MethodCallExpression)expr.Body).Method; this.__new__ = new WrappedCodeObject("__new__", methodInfo, this); // The FlattenHierarchy flag in particular will search upstairs for ClassMember-decorated methods that were declared // in PyClass or PyTypeObject. var classMembers = GetType().GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) .Where(m => m.GetCustomAttributes(typeof(ClassMember), false).Length > 0).ToArray(); foreach (var classMember in classMembers) { // We might have subclasses going on: // 1. Test if we already declared a WrappedCodeObject for this method // 2. If we did, check if it's declaring class is a child of the new candidate // 3. If so, disregard the candidate; we have the better one already. if (this.__dict__.ContainsKey(classMember.Name)) { var existing = this.__dict__[classMember.Name] as WrappedCodeObject; if (existing.MethodBases[0].DeclaringType.IsSubclassOf(classMember.DeclaringType)) { continue; } } __setattr__(classMember.Name, new WrappedCodeObject(classMember.Name, classMember)); } }
public bool MatchesTarget(IPyCallable callable) { return(this.callable.Equals(callable)); }
private CallableDelegateProxy(IPyCallable callable, IInterpreter interpreter, FrameContext contextToUseForCall) { this.callable = callable; this.interpreter = interpreter; this.contextToUseForCall = contextToUseForCall; }