From a19b51bfbfd06b56306c5d573d37906cc078cf38 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 8 Mar 2019 22:37:18 -0800 Subject: [PATCH 1/6] cleaned up MethodBinder.Bind a bit --- src/runtime/methodbinder.cs | 271 ++++++++++++++++++------------------ 1 file changed, 136 insertions(+), 135 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 5e800c36f..c77527d78 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -282,7 +282,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth var pynargs = (int)Runtime.PyTuple_Size(args); object arg; var isGeneric = false; - ArrayList defaultArgList = null; if (info != null) { _methods = new MethodBase[1]; @@ -301,180 +300,151 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth isGeneric = true; } ParameterInfo[] pi = mi.GetParameters(); - var clrnargs = pi.Length; - var match = false; - var arrayStart = -1; - var outs = 0; + ArrayList defaultArgList; + int arrayStart; - if (pynargs == clrnargs) - { - match = true; + if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { + continue; } - else if (pynargs < clrnargs) + var outs = 0; + var margs = new object[pi.Length]; + + for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) { - match = true; - defaultArgList = new ArrayList(); - for (var v = pynargs; v < clrnargs; v++) + IntPtr op; + if (paramIndex >= pynargs) { - if (pi[v].DefaultValue == DBNull.Value) + if (defaultArgList != null) { - match = false; - } - else - { - defaultArgList.Add(pi[v].DefaultValue); + margs[paramIndex] = defaultArgList[paramIndex - pynargs]; } + + continue; } - } - else if (pynargs > clrnargs && clrnargs > 0 && - Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute))) - { - // This is a `foo(params object[] bar)` style method - match = true; - arrayStart = clrnargs - 1; - } - if (match) - { - var margs = new object[clrnargs]; + if (arrayStart == paramIndex) + { + // map remaining Python arguments to a tuple since + // the managed function accepts it - hopefully :] + op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); + } + else + { + op = Runtime.PyTuple_GetItem(args, paramIndex); + } - for (int n = 0; n < clrnargs; n++) + // this logic below handles cases when multiple overloading methods + // are ambiguous, hence comparison between Python and CLR types + // is necessary + clrtype = null; + IntPtr pyoptype; + if (_methods.Length > 1) { - IntPtr op; - if (n < pynargs) + pyoptype = IntPtr.Zero; + pyoptype = Runtime.PyObject_Type(op); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) { - if (arrayStart == n) - { - // map remaining Python arguments to a tuple since - // the managed function accepts it - hopefully :] - op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); - } - else - { - op = Runtime.PyTuple_GetItem(args, n); - } - - // this logic below handles cases when multiple overloading methods - // are ambiguous, hence comparison between Python and CLR types - // is necessary - clrtype = null; - IntPtr pyoptype; - if (_methods.Length > 1) - { - pyoptype = IntPtr.Zero; - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - clrtype = Converter.GetTypeByAlias(pyoptype); - } - Runtime.XDecref(pyoptype); - } + clrtype = Converter.GetTypeByAlias(pyoptype); + } + Runtime.XDecref(pyoptype); + } - if (clrtype != null) + if (clrtype != null) + { + var typematch = false; + if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype)) + { + IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType); + pyoptype = Runtime.PyObject_Type(op); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) { - var typematch = false; - if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype)) + if (pytype != pyoptype) { - IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType); - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - if (pytype != pyoptype) - { - typematch = false; - } - else - { - typematch = true; - clrtype = pi[n].ParameterType; - } - } - if (!typematch) - { - // this takes care of enum values - TypeCode argtypecode = Type.GetTypeCode(pi[n].ParameterType); - TypeCode paramtypecode = Type.GetTypeCode(clrtype); - if (argtypecode == paramtypecode) - { - typematch = true; - clrtype = pi[n].ParameterType; - } - } - Runtime.XDecref(pyoptype); - if (!typematch) - { - margs = null; - break; - } + typematch = false; } else { typematch = true; - clrtype = pi[n].ParameterType; + clrtype = pi[paramIndex].ParameterType; } } - else + if (!typematch) { - clrtype = pi[n].ParameterType; - } - - if (pi[n].IsOut || clrtype.IsByRef) - { - outs++; + // this takes care of enum values + TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType); + TypeCode paramtypecode = Type.GetTypeCode(clrtype); + if (argtypecode == paramtypecode) + { + typematch = true; + clrtype = pi[paramIndex].ParameterType; + } } - - if (!Converter.ToManaged(op, clrtype, out arg, false)) + Runtime.XDecref(pyoptype); + if (!typematch) { - Exceptions.Clear(); margs = null; break; } - if (arrayStart == n) - { - // GetSlice() creates a new reference but GetItem() - // returns only a borrow reference. - Runtime.XDecref(op); - } - margs[n] = arg; } else { - if (defaultArgList != null) - { - margs[n] = defaultArgList[n - pynargs]; - } + typematch = true; + clrtype = pi[paramIndex].ParameterType; } } + else + { + clrtype = pi[paramIndex].ParameterType; + } - if (margs == null) + if (pi[paramIndex].IsOut || clrtype.IsByRef) { - continue; + outs++; } - object target = null; - if (!mi.IsStatic && inst != IntPtr.Zero) + if (!Converter.ToManaged(op, clrtype, out arg, false)) { - //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); - // InvalidCastException: Unable to cast object of type - // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' - var co = ManagedType.GetManagedObject(inst) as CLRObject; - - // Sanity check: this ensures a graceful exit if someone does - // something intentionally wrong like call a non-static method - // on the class rather than on an instance of the class. - // XXX maybe better to do this before all the other rigmarole. - if (co == null) - { - return null; - } - target = co.inst; + Exceptions.Clear(); + margs = null; + break; } + if (arrayStart == paramIndex) + { + // GetSlice() creates a new reference but GetItem() + // returns only a borrow reference. + Runtime.XDecref(op); + } + margs[paramIndex] = arg; + } - return new Binding(mi, target, margs, outs); + if (margs == null) + { + continue; } + + object target = null; + if (!mi.IsStatic && inst != IntPtr.Zero) + { + //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); + // InvalidCastException: Unable to cast object of type + // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' + var co = ManagedType.GetManagedObject(inst) as CLRObject; + + // Sanity check: this ensures a graceful exit if someone does + // something intentionally wrong like call a non-static method + // on the class rather than on an instance of the class. + // XXX maybe better to do this before all the other rigmarole. + if (co == null) + { + return null; + } + target = co.inst; + } + + return new Binding(mi, target, margs, outs); } // We weren't able to find a matching method but at least one // is a generic method and info is null. That happens when a generic @@ -489,6 +459,37 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } + static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList) + { + defaultArgList = null; + var match = false; + paramsArrayStart = -1; + + if (pynargs == pi.Length) + { + match = true; + } else if (pynargs < pi.Length) + { + match = true; + defaultArgList = new ArrayList(); + for (var v = pynargs; v < pi.Length; v++) { + if (pi[v].DefaultValue == DBNull.Value) { + match = false; + } else { + defaultArgList.Add(pi[v].DefaultValue); + } + } + } else if (pynargs > pi.Length && pi.Length > 0 && + Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute))) + { + // This is a `foo(params object[] bar)` style method + match = true; + paramsArrayStart = pi.Length - 1; + } + + return match; + } + internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw) { return Invoke(inst, args, kw, null, null); From 0bb5a450d6ad9965646f9391669b9a92abd27269 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 9 Mar 2019 00:42:55 -0800 Subject: [PATCH 2/6] a bit more refactoring of MethodBinder.Bind --- src/runtime/methodbinder.cs | 177 +++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index c77527d78..be526550a 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -291,7 +291,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth { _methods = GetMethods(); } - Type clrtype; + // TODO: Clean up foreach (MethodBase mi in _methods) { @@ -303,7 +303,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth ArrayList defaultArgList; int arrayStart; - if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { + if (!MatchesArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { continue; } var outs = 0; @@ -311,7 +311,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) { - IntPtr op; if (paramIndex >= pynargs) { if (defaultArgList != null) @@ -322,85 +321,21 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth continue; } - if (arrayStart == paramIndex) - { + IntPtr op = (arrayStart == paramIndex) // map remaining Python arguments to a tuple since // the managed function accepts it - hopefully :] - op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); - } - else - { - op = Runtime.PyTuple_GetItem(args, paramIndex); - } - - // this logic below handles cases when multiple overloading methods - // are ambiguous, hence comparison between Python and CLR types - // is necessary - clrtype = null; - IntPtr pyoptype; - if (_methods.Length > 1) - { - pyoptype = IntPtr.Zero; - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - clrtype = Converter.GetTypeByAlias(pyoptype); - } - Runtime.XDecref(pyoptype); - } + ? Runtime.PyTuple_GetSlice(args, arrayStart, pynargs) + : Runtime.PyTuple_GetItem(args, paramIndex); + var parameter = pi[paramIndex]; - if (clrtype != null) - { - var typematch = false; - if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype)) - { - IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType); - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - if (pytype != pyoptype) - { - typematch = false; - } - else - { - typematch = true; - clrtype = pi[paramIndex].ParameterType; - } - } - if (!typematch) - { - // this takes care of enum values - TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType); - TypeCode paramtypecode = Type.GetTypeCode(clrtype); - if (argtypecode == paramtypecode) - { - typematch = true; - clrtype = pi[paramIndex].ParameterType; - } - } - Runtime.XDecref(pyoptype); - if (!typematch) - { - margs = null; - break; - } - } - else - { - typematch = true; - clrtype = pi[paramIndex].ParameterType; - } - } - else - { - clrtype = pi[paramIndex].ParameterType; + var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: _methods.Length > 1); + if (clrtype == null) { + margs = null; + break; } - if (pi[paramIndex].IsOut || clrtype.IsByRef) + if (parameter.IsOut || clrtype.IsByRef) { outs++; } @@ -459,32 +394,104 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } - static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList) + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) + { + // this logic below handles cases when multiple overloading methods + // are ambiguous, hence comparison between Python and CLR types + // is necessary + Type clrtype = null; + IntPtr pyoptype; + if (needsResolution) + { + // HACK: each overload should be weighted in some way instead + pyoptype = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) + { + clrtype = Converter.GetTypeByAlias(pyoptype); + } + Runtime.XDecref(pyoptype); + } + + if (clrtype != null) + { + var typematch = false; + if ((parameterType != typeof(object)) && (parameterType != clrtype)) + { + IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType); + pyoptype = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) + { + if (pytype != pyoptype) + { + typematch = false; + } + else + { + typematch = true; + clrtype = parameterType; + } + } + if (!typematch) + { + // this takes care of enum values + TypeCode argtypecode = Type.GetTypeCode(parameterType); + TypeCode paramtypecode = Type.GetTypeCode(clrtype); + if (argtypecode == paramtypecode) + { + typematch = true; + clrtype = parameterType; + } + } + Runtime.XDecref(pyoptype); + if (!typematch) + { + return null; + } + } + else + { + typematch = true; + clrtype = parameterType; + } + } + else + { + clrtype = parameterType; + } + + return clrtype; + } + + static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, + out int paramsArrayStart, + out ArrayList defaultArgList) { defaultArgList = null; var match = false; paramsArrayStart = -1; - if (pynargs == pi.Length) + if (argumentCount == parameters.Length) { match = true; - } else if (pynargs < pi.Length) + } else if (argumentCount < parameters.Length) { match = true; defaultArgList = new ArrayList(); - for (var v = pynargs; v < pi.Length; v++) { - if (pi[v].DefaultValue == DBNull.Value) { + for (var v = argumentCount; v < parameters.Length; v++) { + if (parameters[v].DefaultValue == DBNull.Value) { match = false; } else { - defaultArgList.Add(pi[v].DefaultValue); + defaultArgList.Add(parameters[v].DefaultValue); } } - } else if (pynargs > pi.Length && pi.Length > 0 && - Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute))) + } else if (argumentCount > parameters.Length && parameters.Length > 0 && + Attribute.IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute))) { // This is a `foo(params object[] bar)` style method match = true; - paramsArrayStart = pi.Length - 1; + paramsArrayStart = parameters.Length - 1; } return match; From 04b77d9b904989c2132e71f742e65f15da931e46 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Mar 2019 16:00:06 -0700 Subject: [PATCH 3/6] extracted TryConvertArguments from MethodBinder.Bind --- src/runtime/methodbinder.cs | 120 ++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index be526550a..b3c75a377 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -280,7 +280,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth // loop to find match, return invoker w/ or /wo error MethodBase[] _methods = null; var pynargs = (int)Runtime.PyTuple_Size(args); - object arg; var isGeneric = false; if (info != null) { @@ -301,59 +300,15 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth } ParameterInfo[] pi = mi.GetParameters(); ArrayList defaultArgList; - int arrayStart; + bool paramsArray; - if (!MatchesArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { + if (!MatchesArgumentCount(pynargs, pi, out paramsArray, out defaultArgList)) { continue; } var outs = 0; - var margs = new object[pi.Length]; - - for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) - { - if (paramIndex >= pynargs) - { - if (defaultArgList != null) - { - margs[paramIndex] = defaultArgList[paramIndex - pynargs]; - } - - continue; - } - - IntPtr op = (arrayStart == paramIndex) - // map remaining Python arguments to a tuple since - // the managed function accepts it - hopefully :] - ? Runtime.PyTuple_GetSlice(args, arrayStart, pynargs) - : Runtime.PyTuple_GetItem(args, paramIndex); - - var parameter = pi[paramIndex]; - - var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: _methods.Length > 1); - if (clrtype == null) { - margs = null; - break; - } - - if (parameter.IsOut || clrtype.IsByRef) - { - outs++; - } - - if (!Converter.ToManaged(op, clrtype, out arg, false)) - { - Exceptions.Clear(); - margs = null; - break; - } - if (arrayStart == paramIndex) - { - // GetSlice() creates a new reference but GetItem() - // returns only a borrow reference. - Runtime.XDecref(op); - } - margs[paramIndex] = arg; - } + var margs = TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList, + needsResolution: _methods.Length > 1, + outs: out outs); if (margs == null) { @@ -394,6 +349,65 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } + static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, + IntPtr args, int pyArgCount, + ArrayList defaultArgList, + bool needsResolution, + out int outs) + { + outs = 0; + var margs = new object[pi.Length]; + int arrayStart = paramsArray ? pi.Length - 1 : -1; + + for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) + { + if (paramIndex >= pyArgCount) + { + if (defaultArgList != null) + { + margs[paramIndex] = defaultArgList[paramIndex - pyArgCount]; + } + + continue; + } + + IntPtr op = (arrayStart == paramIndex) + // map remaining Python arguments to a tuple since + // the managed function accepts it - hopefully :] + ? Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount) + : Runtime.PyTuple_GetItem(args, paramIndex); + + var parameter = pi[paramIndex]; + + var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: needsResolution); + if (clrtype == null) + { + return null; + } + + if (parameter.IsOut || clrtype.IsByRef) + { + outs++; + } + + object arg; + if (!Converter.ToManaged(op, clrtype, out arg, false)) + { + Exceptions.Clear(); + return null; + } + if (arrayStart == paramIndex) + { + // GetSlice() creates a new reference but GetItem() + // returns only a borrow reference. + Runtime.XDecref(op); + } + margs[paramIndex] = arg; + } + + return margs; + } + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) { // this logic below handles cases when multiple overloading methods @@ -465,12 +479,12 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool } static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, - out int paramsArrayStart, + out bool paramsArray, out ArrayList defaultArgList) { defaultArgList = null; var match = false; - paramsArrayStart = -1; + paramsArray = false; if (argumentCount == parameters.Length) { @@ -491,7 +505,7 @@ static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, { // This is a `foo(params object[] bar)` style method match = true; - paramsArrayStart = parameters.Length - 1; + paramsArray = true; } return match; From 1dadc8a472862e97a5a66011d3ffcc3bb0df2150 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Mar 2019 16:35:10 -0700 Subject: [PATCH 4/6] extracted TryConvertArgument from MethodBinder.TryConvertArguments --- src/runtime/methodbinder.cs | 46 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index b3c75a377..4ceab7faf 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -371,43 +371,57 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, continue; } + var parameter = pi[paramIndex]; IntPtr op = (arrayStart == paramIndex) // map remaining Python arguments to a tuple since // the managed function accepts it - hopefully :] ? Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount) : Runtime.PyTuple_GetItem(args, paramIndex); - var parameter = pi[paramIndex]; - - var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: needsResolution); - if (clrtype == null) + bool isOut; + if (!TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { return null; } - if (parameter.IsOut || clrtype.IsByRef) - { - outs++; - } - - object arg; - if (!Converter.ToManaged(op, clrtype, out arg, false)) - { - Exceptions.Clear(); - return null; - } if (arrayStart == paramIndex) { + // TODO: is this a bug? Should this happen even if the conversion fails? // GetSlice() creates a new reference but GetItem() // returns only a borrow reference. Runtime.XDecref(op); } - margs[paramIndex] = arg; + + if (parameter.IsOut || isOut) + { + outs++; + } } return margs; } + static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, + out object arg, out bool isOut) + { + arg = null; + isOut = false; + var clrtype = TryComputeClrArgumentType(parameterType, op, needsResolution: needsResolution); + if (clrtype == null) + { + return false; + } + + if (!Converter.ToManaged(op, clrtype, out arg, false)) + { + Exceptions.Clear(); + return false; + } + + isOut = clrtype.IsByRef; + return true; + } + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) { // this logic below handles cases when multiple overloading methods From 3edad62bf79c0fc3013d00141d1e9f2dc729dc8d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Mar 2019 16:42:10 -0700 Subject: [PATCH 5/6] added a documentation comment for MethodBinder.TryConvertArguments --- src/runtime/methodbinder.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 4ceab7faf..7471d5d7c 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -349,6 +349,18 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } + /// + /// Attempts to convert Python argument tuple into an array of managed objects, + /// that can be passed to a method. + /// + /// Information about expected parameters + /// true, if the last parameter is a params array. + /// A pointer to the Python argument tuple + /// Number of arguments, passed by Python + /// A list of default values for omitted parameters + /// true, if overloading resolution is required + /// Returns number of output parameters + /// An array of .NET arguments, that can be passed to a method. static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, IntPtr args, int pyArgCount, ArrayList defaultArgList, From d866e33b7fbc16049f7be48868042258b8b074b3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 Mar 2019 14:42:58 -0700 Subject: [PATCH 6/6] updated AUTHORS and CHANGELOG --- AUTHORS.md | 1 + CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index fe2d2b172..53108463e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -43,6 +43,7 @@ - Sean Freitag ([@cowboygneox](https://github.com/cowboygneox)) - Serge Weinstock ([@sweinst](https://github.com/sweinst)) - Simon Mourier ([@smourier](https://github.com/smourier)) +- Victor Milovanov ([@lostmsu](https://github.com/lostmsu)) - Viktoria Kovescses ([@vkovec](https://github.com/vkovec)) - Ville M. Vainio ([@vivainio](https://github.com/vivainio)) - Virgil Dupras ([@hsoft](https://github.com/hsoft)) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3816cd0c..17c1780ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Reattach python exception traceback information (#545) - PythonEngine.Intialize will now call `Py_InitializeEx` with a default value of 0, so signals will not be configured by default on embedding. This is different from the previous behaviour, where `Py_Initialize` was called instead, which sets initSigs to 1. ([#449][i449]) +- Refactored MethodBinder.Bind in preparation to make it extensible (#829) ### Fixed