Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
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
  • Loading branch information
lostmsu committed Nov 2, 2022
commit 5c1e02f0b5d38def43e8547b5ca701d724f80c80
28 changes: 20 additions & 8 deletions src/runtime/Types/ClassDerived.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ private static void AddVirtualMethod(MethodInfo method, Type baseType, TypeBuild
il.Emit(OpCodes.Ldloc_0);

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

il.DeclareLocal(typeof(object[]));
il.DeclareLocal(typeof(RuntimeMethodHandle));
il.DeclareLocal(typeof(RuntimeTypeHandle));

// this
il.Emit(OpCodes.Ldarg_0);
Expand Down Expand Up @@ -546,6 +548,11 @@ private static void AddPythonMethod(string methodName, PyObject func, TypeBuilde
il.Emit(OpCodes.Ldloca_S, 1);
il.Emit(OpCodes.Initobj, typeof(RuntimeMethodHandle));
il.Emit(OpCodes.Ldloc_1);

// type handle is also not required
il.Emit(OpCodes.Ldloca_S, 2);
il.Emit(OpCodes.Initobj, typeof(RuntimeTypeHandle));
il.Emit(OpCodes.Ldloc_2);
#pragma warning disable CS0618 // PythonDerivedType is for internal use only

// invoke the method
Expand Down Expand Up @@ -698,7 +705,7 @@ public class PythonDerivedType
/// class) it calls it, otherwise it calls the base method.
/// </summary>
public static T? InvokeMethod<T>(IPythonDerivedType obj, string methodName, string origMethodName,
object[] args, RuntimeMethodHandle methodHandle)
object[] args, RuntimeMethodHandle methodHandle, RuntimeTypeHandle declaringTypeHandle)
{
var self = GetPyObj(obj);

Expand All @@ -724,7 +731,10 @@ public class PythonDerivedType
}

PyObject py_result = method.Invoke(pyargs);
PyTuple? result_tuple = MarshalByRefsBack(args, methodHandle, py_result, outsOffset: 1);
var clrMethod = methodHandle != default
? MethodBase.GetMethodFromHandle(methodHandle, declaringTypeHandle)
: null;
PyTuple? result_tuple = MarshalByRefsBack(args, clrMethod, py_result, outsOffset: 1);
return result_tuple is not null
? result_tuple[0].As<T>()
: py_result.As<T>();
Expand Down Expand Up @@ -754,7 +764,7 @@ public class PythonDerivedType
}

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

PyObject py_result = method.Invoke(pyargs);
MarshalByRefsBack(args, methodHandle, py_result, outsOffset: 0);
var clrMethod = methodHandle != default
? MethodBase.GetMethodFromHandle(methodHandle, declaringTypeHandle)
: null;
MarshalByRefsBack(args, clrMethod, py_result, outsOffset: 0);
return;
}
}
Expand Down Expand Up @@ -811,12 +824,11 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s
/// as a tuple of new values for those arguments, and updates corresponding
/// elements of <paramref name="args"/> array.
/// </summary>
private static PyTuple? MarshalByRefsBack(object?[] args, RuntimeMethodHandle methodHandle, PyObject pyResult, int outsOffset)
private static PyTuple? MarshalByRefsBack(object?[] args, MethodBase? method, PyObject pyResult, int outsOffset)
{
if (methodHandle == default) return null;
if (method is null) return null;

var originalMethod = MethodBase.GetMethodFromHandle(methodHandle);
var parameters = originalMethod.GetParameters();
var parameters = method.GetParameters();
PyTuple? outs = null;
int byrefIndex = 0;
for (int i = 0; i < parameters.Length; ++i)
Expand Down