internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo) { Binding binding = Bind(inst, args, kw, info, methodinfo); object result; IntPtr ts = IntPtr.Zero; if (binding == null) { var value = "No method matches given arguments"; if (methodinfo != null && methodinfo.Length > 0) { value += $" for {methodinfo[0].Name}"; } Exceptions.SetError(Exceptions.TypeError, value); return(IntPtr.Zero); } if (allow_threads) { ts = PythonEngine.BeginAllowThreads(); } try { result = binding.info.Invoke(binding.inst, BindingFlags.Default, null, binding.args, null); } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } if (allow_threads) { PythonEngine.EndAllowThreads(ts); } Exceptions.SetError(e); return(IntPtr.Zero); } if (allow_threads) { PythonEngine.EndAllowThreads(ts); } // If there are out parameters, we return a tuple containing // the result followed by the out parameters. If there is only // one out parameter and the return type of the method is void, // we return the out parameter as the result to Python (for // code compatibility with ironpython). var mi = (MethodInfo)binding.info; if (binding.outs == 1 && mi.ReturnType == typeof(void)) { } if (binding.outs > 0) { ParameterInfo[] pi = mi.GetParameters(); int c = pi.Length; var n = 0; IntPtr t = Runtime.PyTuple_New(binding.outs + 1); IntPtr v = Converter.ToPython(result, mi.ReturnType); Runtime.PyTuple_SetItem(t, n, v); n++; for (var i = 0; i < c; i++) { Type pt = pi[i].ParameterType; if (pi[i].IsOut || pt.IsByRef) { v = Converter.ToPython(binding.args[i], pt); Runtime.PyTuple_SetItem(t, n, v); n++; } } if (binding.outs == 1 && mi.ReturnType == typeof(void)) { v = Runtime.PyTuple_GetItem(t, 1); Runtime.XIncref(v); Runtime.XDecref(t); return(v); } return(t); } return(Converter.ToPython(result, mi.ReturnType)); }
/// <summary> /// Allows ctor selection to be limited to a single attempt at a /// match by providing the MethodBase to use instead of searching /// the entire MethodBinder.list (generic ArrayList) /// </summary> /// <param name="inst"> (possibly null) instance </param> /// <param name="args"> PyObject* to the arg tuple </param> /// <param name="kw"> PyObject* to the keyword args dict </param> /// <param name="info"> The sole ContructorInfo to use or null </param> /// <returns> The result of the constructor call with converted params </returns> /// <remarks> /// 2010-07-24 BC: I added the info parameter to the call to Bind() /// Binding binding = this.Bind(inst, args, kw, info); /// to take advantage of Bind()'s ability to use a single MethodBase (CI or MI). /// </remarks> internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info) { Object result; if (_containingType.IsValueType && !_containingType.IsPrimitive && !_containingType.IsEnum && _containingType != typeof(decimal) && Runtime.PyTuple_Size(args) == 0) { // If you are trying to construct an instance of a struct by // calling its default constructor, that ConstructorInfo // instance will not appear in reflection and the object must // instead be constructed via a call to // Activator.CreateInstance(). try { result = Activator.CreateInstance(_containingType); } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } Exceptions.SetError(e); return(null); } return(result); } Binding binding = this.Bind(inst, args, kw, info); if (binding == null) { // It is possible for __new__ to be invoked on construction // of a Python subclass of a managed class, so args may // reflect more args than are required to instantiate the // class. So if we cant find a ctor that matches, we'll see // if there is a default constructor and, if so, assume that // any extra args are intended for the subclass' __init__. IntPtr eargs = Runtime.PyTuple_New(0); binding = this.Bind(inst, eargs, kw); Runtime.XDecref(eargs); if (binding == null) { Exceptions.SetError(Exceptions.TypeError, "no constructor matches given arguments" ); return(null); } } // Fire the selected ctor and catch errors... ConstructorInfo ci = (ConstructorInfo)binding.info; // Object construction is presumed to be non-blocking and fast // enough that we shouldn't really need to release the GIL. try { result = ci.Invoke(binding.args); } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } Exceptions.SetError(e); return(null); } return(result); }