Open
Description
Environment
- Pythonnet version: >= 3.0.0 ( version < 3.0.0 are ok)
- Python version: 3.9, 3.10, 3.11, 3.12...
- Operating System: Windows x64
- .NET Runtime: 4.6.2 .net framework
Details
Importing a .net assembly written in C++/CLI using a very specific way to define an operator result in an exception:
Python 3.11.4 | packaged by Anaconda, Inc. | (main, Jul 5 2023, 13:47:18) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> clr.AddReference(r"C:\Users\laure\source\repos\Operator\x64\Release\Operator.dll")
<System.Reflection.RuntimeAssembly object at 0x0000029709E3D680>
>>> import Operator
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 676, in _load_unlocked
File "<frozen importlib._bootstrap>", line 573, in module_from_spec
File "<string>", line 15, in create_module
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Python.Runtime.OperatorMethod.IsReverse(MethodBase method)
at Python.Runtime.OperatorMethod.FilterMethods(MethodBase[] methods, MethodBase[]& forwardMethods, MethodBase[]& reverseMethods)
at Python.Runtime.ClassManager.GetClassInfo(Type type, ClassBase impl)
at Python.Runtime.ClassManager.InitClassBase(Type type, ClassBase impl, ReflectedClrType pyType)
at Python.Runtime.ReflectedClrType.GetOrCreate(Type type)
at Python.Runtime.ModuleObject.GetAttribute(String name, Boolean guess)
at Python.Runtime.ModuleObject.LoadNames()
at Python.Runtime.ImportHook.Import(String modname)
at Python.Runtime.CLRModule._load_clr_module(PyObject spec)
This can be reproduce with the minimal code (C++/CLI):
namespace Operator
{
public ref class Matrix
{
public:
Matrix^ operator - ()
{
return gcnew Matrix();
}
};
}
See Operator.zip
Investigation
It seems there is two way to define the operator- in C++/CLI:
Matrix^ operator - ()
And
static Matrix^ operator - (Matrix^ m)
There is no issue when using the second form. Actually in C# only the equivalent of the second form is possible. It explains why this bug is very uncommon.
Source of the exception
The code in pythonnet code triggering this exception (src/runtime/Types/OperatorMethod.cs)
public static bool IsReverse(MethodBase method)
{
Type primaryType = method.IsOpsHelper()
? method.DeclaringType.GetGenericArguments()[0]
: method.DeclaringType;
Type leftOperandType = method.GetParameters()[0].ParameterType;
return leftOperandType != primaryType;
}
The exception is thrown because GetGenericArguments return an empty list.