diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 420fc9435..dd8598e33 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -29,6 +29,8 @@ private Converter() private static Type int64Type; private static Type boolType; private static Type typeType; + private static Type uint64Type; + private static Type uint32Type; static Converter() { @@ -43,13 +45,15 @@ static Converter() decimalType = typeof(Decimal); boolType = typeof(Boolean); typeType = typeof(Type); + uint64Type = typeof(UInt64); + uint32Type = typeof(UInt32); } /// /// Given a builtin Python type, return the corresponding CLR type. /// - internal static Type GetTypeByAlias(IntPtr op) + internal static Type GetTypeByAlias(IntPtr op, Type preferred=null) { if (op == Runtime.PyStringType) return stringType; @@ -57,12 +61,18 @@ internal static Type GetTypeByAlias(IntPtr op) if (op == Runtime.PyUnicodeType) return stringType; - if (op == Runtime.PyIntType) + if (op == Runtime.PyIntType && (preferred == null || preferred == int32Type)) return int32Type; - if (op == Runtime.PyLongType) + if (op == Runtime.PyIntType && (preferred == null || preferred == uint32Type)) + return uint32Type; + + if (op == Runtime.PyLongType && (preferred == null || preferred == int64Type)) return int64Type; + if (op == Runtime.PyLongType && (preferred == null || preferred == uint64Type)) + return uint64Type; + if (op == Runtime.PyFloatType) return doubleType; diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 1b7cc4736..b72e3d963 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -330,6 +330,7 @@ public MatchedMethod(int kwargsMatched, int defaultsNeeded, object[] margs, int ManagedArgs = margs; Outs = outs; Method = mb; + HasPyObjectParameter = mb.GetParameters().Any(x => x.ParameterType == typeof(PyObject)); } public int KwargsMatched { get; } @@ -337,6 +338,7 @@ public MatchedMethod(int kwargsMatched, int defaultsNeeded, object[] margs, int public object[] ManagedArgs { get; } public int Outs { get; } public MethodBase Method { get; } + public bool HasPyObjectParameter { get; } } private readonly struct MismatchedMethod @@ -470,8 +472,15 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth var matchedMethod = new MatchedMethod(kwargsMatched, defaultsNeeded, margs, outs, mi); argMatchedMethods.Add(matchedMethod); } + if (argMatchedMethods.Count > 0) { + // order the matched methods such that PyObject overrides are last, we only care about + // this when there is more than one arg matched method + if (argMatchedMethods.Count > 1) + { + argMatchedMethods = argMatchedMethods.OrderBy(x => x.HasPyObjectParameter).ToList(); + } var bestKwargMatchCount = argMatchedMethods.Max(x => x.KwargsMatched); var fewestDefaultsRequired = argMatchedMethods.Where(x => x.KwargsMatched == bestKwargMatchCount).Min(x => x.DefaultsNeeded); @@ -725,7 +734,7 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool pyoptype = Runtime.PyObject_Type(argument); if (pyoptype != IntPtr.Zero) { - clrtype = Converter.GetTypeByAlias(pyoptype); + clrtype = Converter.GetTypeByAlias(pyoptype, parameterType); } Runtime.XDecref(pyoptype); } diff --git a/src/testing/conversiontest.cs b/src/testing/conversiontest.cs index 1f9d64e1b..f67551bb7 100644 --- a/src/testing/conversiontest.cs +++ b/src/testing/conversiontest.cs @@ -42,7 +42,7 @@ public ConversionTest() } - + public interface ISpam { @@ -63,7 +63,7 @@ public string GetValue() return value; } } - + public class UnicodeString { public string value = "안녕"; @@ -78,4 +78,17 @@ public override string ToString() return value; } } + + public class MethodResolutionInt + { + public IEnumerable MethodA(ulong address, int size) + { + return new byte[10]; + } + + public int MethodA(string dummy, ulong address, int size) + { + return 0; + } + } } diff --git a/tests/test_conversion.py b/tests/test_conversion.py index eec2bcde6..8fa972a3e 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -4,7 +4,7 @@ import pytest import System -from Python.Test import ConversionTest, UnicodeString +from Python.Test import ConversionTest, UnicodeString, MethodResolutionInt from Python.Runtime import PyObjectConversions from Python.Runtime.Codecs import RawProxyEncoder @@ -681,3 +681,15 @@ def CanEncode(self, clr_type): l = ob.ListField l.Add(42) assert ob.ListField.Count == 1 + +def test_int_param_resolution_required(): + """Test resolution of `int` parameters when resolution is needed""" + + mri = MethodResolutionInt() + data = list(mri.MethodA(0x1000, 10)) + assert len(data) == 10 + assert data[0] == 0 + + data = list(mri.MethodA(0x100000000, 10)) + assert len(data) == 10 + assert data[0] == 0