Developer
Developer

Reputation: 103

Calling C# code from python using pythonnet

Following is the C# code. How do I call the GenericMethod() inside the NonGenericClass from Python using pythonnet?

namespace CSharpTestCode
{
    public interface Person
    {
    }

    public class Employee : Person
    {
    }

    public class TempGenericClass<T>
    {
    }

    public class NonGenericClass
    {
        public static T GenericMethod<T>(TempGenericClass<T> tempGeneric) where T : class, Person
        {
            return null;
        }
    }
}

Python code that I tried:

import clr
clr.AddReference(r'\Documents\visual studio 2015\Projects\SamplePythonApp\CSharpTestCode\bin\Debug\CSharpTestCode.dll')
from CSharpTestCode import *

genericMethod = NonGenericClass.GenericMethod(TempGenericClass[Employee]())

Error that I got:

Unhandled Exception: System.ArgumentException: GenericArguments[0], 'CSharpTestCode.TempGenericClass`1[CSharpTestCode.Employee]', on 'T GenericMethod[T](CSharpTestCode.TempGenericClass`1[T])' violates the constraint of type 'T'. ---> System.Security.VerificationException: Method CSharpTestCode.NonGenericClass.GenericMethod: type argument 'CSharpTestCode.TempGenericClass`1[CSharpTestCode.Employee]' violates the constraint of type parameter 'T'.
   at System.RuntimeMethodHandle.GetStubIfNeeded(RuntimeMethodHandleInternal method, RuntimeType declaringType, RuntimeType[] methodInstantiation)
   at System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation)
   --- End of inner exception stack trace ---
   at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
   at System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation)
   at Python.Runtime.MethodBinder.MatchParameters(MethodInfo[] mi, Type[] tp)
   at Python.Runtime.MethodBinder.Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
   at Python.Runtime.MethodBinder.Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
   at Python.Runtime.MethodObject.Invoke(IntPtr target, IntPtr args, IntPtr kw, MethodBase info)
   at Python.Runtime.MethodBinding.tp_call(IntPtr ob, IntPtr args, IntPtr kw)

Upvotes: 5

Views: 3274

Answers (1)

den.run.ai
den.run.ai

Reputation: 5943

I should admit that pythonnet is not supposed to crash CPython interpreter even on this bad example of generic call with invalid arguments to the method.

Here is how to properly make your generic calls with pythonnet, notice how passing wrong types fails properly:

In [3]: NonGenericClass.GenericMethod[Person](TempGenericClass[Person]())


In [4]: NonGenericClass.GenericMethod[Employee](TempGenericClass[Employee]())


In [5]: NonGenericClass.GenericMethod[Person](TempGenericClass[Employee]())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-d13751f7586f> in <module>()
----> 1 NonGenericClass.GenericMethod[Person](TempGenericClass[Employee]())

TypeError: No method matches given arguments


In [6]: NonGenericClass.GenericMethod[Employee](TempGenericClass[Person]())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-04c3c0db6c6b> in <module>()
----> 1 NonGenericClass.GenericMethod[Employee](TempGenericClass[Person]())

TypeError: No method matches given arguments

Upvotes: 3

Related Questions