Skip to content

Commit 5c1e02f

Browse files
committed
fixed resolution of generic methods in Python implementations
since RuntimeMethodHandle does not encode generic arguments, I had to supply RuntimeTypeHandle of the declaring type to be able to get fully specified method
1 parent 461c9c7 commit 5c1e02f

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

src/runtime/Types/ClassDerived.cs

+20-8
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ private static void AddVirtualMethod(MethodInfo method, Type baseType, TypeBuild
436436
il.Emit(OpCodes.Ldloc_0);
437437

438438
il.Emit(OpCodes.Ldtoken, method);
439+
il.Emit(OpCodes.Ldtoken, method.DeclaringType);
439440
#pragma warning disable CS0618 // PythonDerivedType is for internal use only
440441
if (method.ReturnType == typeof(void))
441442
{
@@ -505,6 +506,7 @@ private static void AddPythonMethod(string methodName, PyObject func, TypeBuilde
505506

506507
il.DeclareLocal(typeof(object[]));
507508
il.DeclareLocal(typeof(RuntimeMethodHandle));
509+
il.DeclareLocal(typeof(RuntimeTypeHandle));
508510

509511
// this
510512
il.Emit(OpCodes.Ldarg_0);
@@ -546,6 +548,11 @@ private static void AddPythonMethod(string methodName, PyObject func, TypeBuilde
546548
il.Emit(OpCodes.Ldloca_S, 1);
547549
il.Emit(OpCodes.Initobj, typeof(RuntimeMethodHandle));
548550
il.Emit(OpCodes.Ldloc_1);
551+
552+
// type handle is also not required
553+
il.Emit(OpCodes.Ldloca_S, 2);
554+
il.Emit(OpCodes.Initobj, typeof(RuntimeTypeHandle));
555+
il.Emit(OpCodes.Ldloc_2);
549556
#pragma warning disable CS0618 // PythonDerivedType is for internal use only
550557

551558
// invoke the method
@@ -698,7 +705,7 @@ public class PythonDerivedType
698705
/// class) it calls it, otherwise it calls the base method.
699706
/// </summary>
700707
public static T? InvokeMethod<T>(IPythonDerivedType obj, string methodName, string origMethodName,
701-
object[] args, RuntimeMethodHandle methodHandle)
708+
object[] args, RuntimeMethodHandle methodHandle, RuntimeTypeHandle declaringTypeHandle)
702709
{
703710
var self = GetPyObj(obj);
704711

@@ -724,7 +731,10 @@ public class PythonDerivedType
724731
}
725732

726733
PyObject py_result = method.Invoke(pyargs);
727-
PyTuple? result_tuple = MarshalByRefsBack(args, methodHandle, py_result, outsOffset: 1);
734+
var clrMethod = methodHandle != default
735+
? MethodBase.GetMethodFromHandle(methodHandle, declaringTypeHandle)
736+
: null;
737+
PyTuple? result_tuple = MarshalByRefsBack(args, clrMethod, py_result, outsOffset: 1);
728738
return result_tuple is not null
729739
? result_tuple[0].As<T>()
730740
: py_result.As<T>();
@@ -754,7 +764,7 @@ public class PythonDerivedType
754764
}
755765

756766
public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName,
757-
object?[] args, RuntimeMethodHandle methodHandle)
767+
object?[] args, RuntimeMethodHandle methodHandle, RuntimeTypeHandle declaringTypeHandle)
758768
{
759769
var self = GetPyObj(obj);
760770
if (null != self.Ref)
@@ -779,7 +789,10 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s
779789
}
780790

781791
PyObject py_result = method.Invoke(pyargs);
782-
MarshalByRefsBack(args, methodHandle, py_result, outsOffset: 0);
792+
var clrMethod = methodHandle != default
793+
? MethodBase.GetMethodFromHandle(methodHandle, declaringTypeHandle)
794+
: null;
795+
MarshalByRefsBack(args, clrMethod, py_result, outsOffset: 0);
783796
return;
784797
}
785798
}
@@ -811,12 +824,11 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s
811824
/// as a tuple of new values for those arguments, and updates corresponding
812825
/// elements of <paramref name="args"/> array.
813826
/// </summary>
814-
private static PyTuple? MarshalByRefsBack(object?[] args, RuntimeMethodHandle methodHandle, PyObject pyResult, int outsOffset)
827+
private static PyTuple? MarshalByRefsBack(object?[] args, MethodBase? method, PyObject pyResult, int outsOffset)
815828
{
816-
if (methodHandle == default) return null;
829+
if (method is null) return null;
817830

818-
var originalMethod = MethodBase.GetMethodFromHandle(methodHandle);
819-
var parameters = originalMethod.GetParameters();
831+
var parameters = method.GetParameters();
820832
PyTuple? outs = null;
821833
int byrefIndex = 0;
822834
for (int i = 0; i < parameters.Length; ++i)

0 commit comments

Comments
 (0)