diff --git a/src/runtime/Types/ClassDerived.cs b/src/runtime/Types/ClassDerived.cs index 02288faee..cf6d9b16b 100644 --- a/src/runtime/Types/ClassDerived.cs +++ b/src/runtime/Types/ClassDerived.cs @@ -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)) { @@ -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); @@ -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 @@ -698,7 +705,7 @@ public class PythonDerivedType /// class) it calls it, otherwise it calls the base method. /// public static T? InvokeMethod(IPythonDerivedType obj, string methodName, string origMethodName, - object[] args, RuntimeMethodHandle methodHandle) + object[] args, RuntimeMethodHandle methodHandle, RuntimeTypeHandle declaringTypeHandle) { var self = GetPyObj(obj); @@ -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() : py_result.As(); @@ -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) @@ -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; } } @@ -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 array. /// - 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) diff --git a/src/testing/interfacetest.cs b/src/testing/interfacetest.cs index 7c5d937b9..a1a7106b5 100644 --- a/src/testing/interfacetest.cs +++ b/src/testing/interfacetest.cs @@ -79,7 +79,7 @@ private interface IPrivate { } } - + public interface IOutArg { string MyMethod_Out(string name, out int index); @@ -93,4 +93,25 @@ public static int CallMyMethod_Out(IOutArg myInterface) return index; } } + + public interface IGenericInterface + { + public T Get(T x); + } + + public class SpecificInterfaceUser + { + public SpecificInterfaceUser(IGenericInterface some, int x) + { + some.Get(x); + } + } + + public class GenericInterfaceUser + { + public GenericInterfaceUser(IGenericInterface some, T x) + { + some.Get(x); + } + } } diff --git a/tests/test_subclass.py b/tests/test_subclass.py index fa82c3663..a51e89da3 100644 --- a/tests/test_subclass.py +++ b/tests/test_subclass.py @@ -9,7 +9,7 @@ import System import pytest from Python.Test import (IInterfaceTest, SubClassTest, EventArgsTest, - FunctionsTest) + FunctionsTest, IGenericInterface) from System.Collections.Generic import List @@ -29,6 +29,17 @@ def bar(self, x, i): return InterfaceTestClass +def interface_generic_class_fixture(subnamespace): + + class GenericInterfaceImpl(IGenericInterface[int]): + __namespace__ = "Python.Test." + subnamespace + + def Get(self, x): + return x + + return GenericInterfaceImpl + + def derived_class_fixture(subnamespace): """Delay creation of class until test starts.""" @@ -306,3 +317,13 @@ class Derived(BaseClass): import gc gc.collect() + +def test_generic_interface(): + from System import Int32 + from Python.Test import GenericInterfaceUser, SpecificInterfaceUser + + GenericInterfaceImpl = interface_generic_class_fixture(test_generic_interface.__name__) + + obj = GenericInterfaceImpl() + SpecificInterfaceUser(obj, Int32(0)) + GenericInterfaceUser[Int32](obj, Int32(0)) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy