Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python classes cannot inherit from C# interfaces that themselves inherit from C# interfaces with methods #2526

Open
sean-anderson-seco opened this issue Dec 9, 2024 · 7 comments

Comments

@sean-anderson-seco
Copy link

sean-anderson-seco commented Dec 9, 2024

Python classes cannot inherit from C# interfaces that themselves inherit from C# interfaces with methods:

namespace A
{
    public interface B
    {
        void C();
    }

    public interface D : B
    {
    }
}
import clr

clr.AddReference('A')
import A

class E(A.D):
    __namespace__ = 'F'
    def C(self):
        pass

Output:

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
TypeError: Failed to create Python type for F.E

Extending from B works. It also works if C is removed from B.

Possibly related to #2511. Reverting to 3.0.3 (before 9ebfbde) provides the moderately-more-useful error TypeError: VTable setup of type F.E failed.

Please do NOT convert this to a discussion. It is a real bug that requires fixing. As noted above, providing a definition for C does not affect whether the bug occurs.

I have tested this with mono 6.8 and 6.12, as well as with MSCV. The latter gives the slightly-different error:

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
    class E(A.D):
TypeError: Method 'C' in type 'F.E' from assembly 'Python.Runtime.Dynamic, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.

Note that C was defined as above.


As a workaround, the following can be done...

import clr

clr.AddReference('A')
import A

class E(A.B):
    __namespace__ = 'F'

class G(E, A.D):
    __namespace__ = 'F'
    def C(self):
        pass

G().C()

And for some reason C has to be implemented in G and not E:

System.NotImplementedException: Python object does not have a 'C' method
  at Python.Runtime.PythonDerivedType.InvokeMethodVoid (Python.Runtime.IPythonDerivedType obj, System.String methodName, System.String origMethodName, System.Object[] args, System.RuntimeMethodHandle methodHandle, System.RuntimeTypeHandle declaringTypeHandle) [0x00151] in <e8135b23d9064b84a255057569ff100a>:0 
  at F.E.C () [0x00000] in <d16dd79070534f72b8760f94ab2e0924>:0 
  at F.G._E__C () [0x00000] in <d16dd79070534f72b8760f94ab2e0924>:0 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0007c] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 14, in <module>
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotImplementedException: Python object does not have a 'C' method
  at Python.Runtime.PythonDerivedType.InvokeMethodVoid (Python.Runtime.IPythonDerivedType obj, System.String methodName, System.String origMethodName, System.Object[] args, System.RuntimeMethodHandle methodHandle, System.RuntimeTypeHandle declaringTypeHandle) [0x00151] in <e8135b23d9064b84a255057569ff100a>:0 
  at F.E.C () [0x00000] in <d16dd79070534f72b8760f94ab2e0924>:0 
  at F.G._E__C () [0x00000] in <d16dd79070534f72b8760f94ab2e0924>:0 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0007c] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
   --- End of inner exception stack trace ---
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0009a] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
  at System.RuntimeType.InvokeMember (System.String name, System.Reflection.BindingFlags bindingFlags, System.Reflection.Binder binder, System.Object target, System.Object[] providedArgs, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, System.String[] namedParams) [0x007b0] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
  at System.Type.InvokeMember (System.String name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object target, System.Object[] args) [0x00000] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
  at Python.Runtime.PythonDerivedType.InvokeMethodVoid (Python.Runtime.IPythonDerivedType obj, System.String methodName, System.String origMethodName, System.Object[] args, System.RuntimeMethodHandle methodHandle, System.RuntimeTypeHandle declaringTypeHandle) [0x0015d] in <e8135b23d9064b84a255057569ff100a>:0 
  at F.G.C () [0x00000] in <d16dd79070534f72b8760f94ab2e0924>:0 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0007c] in <12b418a7818c4ca0893feeaaf67f1e7f>:0 
@filmor
Copy link
Member

filmor commented Dec 9, 2024

And it was impossible for you to write the small additions in the converted discussion?

On topic: If you want to debug this a bit more and provide a fix, this is where the sub-classes are generated:

internal static NewReference CreateSubType(BorrowedReference py_name, ClassBase py_base_type, IList<Type> interfaces, BorrowedReference dictRef)

@sean-anderson-seco
Copy link
Author

sean-anderson-seco commented Dec 9, 2024

And it was impossible for you to write the small additions in the converted discussion?

It's a bug! Why would you convert it to a discussion unless you think this is intended behavior?

On topic: If you want to debug this a bit more and provide a fix, this is where the sub-classes are generated:

I will have a look, but I was unable to build this project now that xbuild support has been removed. So I can't really work on a fix.

@filmor
Copy link
Member

filmor commented Dec 9, 2024

And it was impossible for you to write the small additions in the converted discussion?

It's a bug! Why would you convert it to a discussion unless you think this is intended behavior?

This is not for you to decide. In the original post, your example had an obvious error that was pointed out to you. You could have easily answered on that thread instead of opening a new issue with almost entirely the same content.

On topic: If you want to debug this a bit more and provide a fix, this is where the sub-classes are generated:

I will have a look, but I was unable to build this project now that xbuild support has been removed. So I can't really work on a fix.

The project can be built straight with dotnet build. If you want to use it from Python, you can run pip install . from the pythonnet directory.

@sean-anderson-seco
Copy link
Author

sean-anderson-seco commented Dec 9, 2024

In the original post, your example had an obvious error that was pointed out to you.

This was not an error. I simply omitted it to make the example clearer. The following code

import clr

clr.AddReference('A')
import A

class E(A.B):
    __namespace__ = 'F'

produces no errors. It is only when invoking E().C() that an exception is raised. So actually implementing C is orthogonal to the above error. And if you had run the code you would have found this behavior too.

The project can be built straight with dotnet build

This is not packaged on Debian/Ubuntu. Maybe at some point I will get around to it.

@filmor
Copy link
Member

filmor commented Dec 9, 2024

@sean-anderson-seco
Copy link
Author

That's a third-party package...

@filmor
Copy link
Member

filmor commented Dec 10, 2024

.NET is available in the Ubuntu package manager feeds. The Microsoft package repository no longer contains .NET packages for Ubuntu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants