@@ -9,9 +9,11 @@ namespace Python.Runtime
9
9
{
10
10
internal static class OperatorMethod
11
11
{
12
+ // Maps the compiled method name in .NET CIL (e.g. op_Addition) to
13
+ // the equivalent Python operator (e.g. __add__) as well as the offset
14
+ // that identifies that operator's slot (e.g. nb_add) in heap space.
12
15
public static Dictionary < string , Tuple < string , int > > OpMethodMap { get ; private set ; }
13
16
14
- private static Dictionary < string , string > _pyOpNames ;
15
17
private static PyObject _opType ;
16
18
17
19
static OperatorMethod ( )
@@ -35,12 +37,6 @@ static OperatorMethod()
35
37
[ "op_Modulus" ] = Tuple . Create ( "__mod__" , TypeOffset . nb_remainder ) ,
36
38
[ "op_OneComplement" ] = Tuple . Create ( "__invert__" , TypeOffset . nb_invert )
37
39
} ;
38
-
39
- _pyOpNames = new Dictionary < string , string > ( ) ;
40
- foreach ( string name in OpMethodMap . Keys )
41
- {
42
- _pyOpNames . Add ( GetPyMethodName ( name ) , name ) ;
43
- }
44
40
}
45
41
46
42
public static void Initialize ( )
@@ -62,11 +58,6 @@ public static bool IsOperatorMethod(string methodName)
62
58
return OpMethodMap . ContainsKey ( methodName ) ;
63
59
}
64
60
65
- public static bool IsPyOperatorMethod ( string pyMethodName )
66
- {
67
- return _pyOpNames . ContainsKey ( pyMethodName ) ;
68
- }
69
-
70
61
public static bool IsOperatorMethod ( MethodBase method )
71
62
{
72
63
if ( ! method . IsSpecialName )
@@ -75,7 +66,12 @@ public static bool IsOperatorMethod(MethodBase method)
75
66
}
76
67
return OpMethodMap . ContainsKey ( method . Name ) ;
77
68
}
78
-
69
+ /// <summary>
70
+ /// For the operator methods of a CLR type, set the special slots of the
71
+ /// corresponding Python type's operator methods.
72
+ /// </summary>
73
+ /// <param name="pyType"></param>
74
+ /// <param name="clrType"></param>
79
75
public static void FixupSlots ( IntPtr pyType , Type clrType )
80
76
{
81
77
const BindingFlags flags = BindingFlags . Public | BindingFlags . Static ;
@@ -86,10 +82,16 @@ public static void FixupSlots(IntPtr pyType, Type clrType)
86
82
{
87
83
continue ;
88
84
}
89
- var slotdef = OpMethodMap [ method . Name ] ;
90
- int offset = slotdef . Item2 ;
85
+ int offset = OpMethodMap [ method . Name ] . Item2 ;
86
+ // Copy the default implementation of e.g. the nb_add slot,
87
+ // which simply calls __add__ on the type.
91
88
IntPtr func = Marshal . ReadIntPtr ( _opType . Handle , offset ) ;
89
+ // Write the slot definition of the target Python type, so
90
+ // that we can later modify __add___ and it will be called
91
+ // when used with a Python operator.
92
+ // https://tenthousandmeters.com/blog/python-behind-the-scenes-6-how-python-object-system-works/
92
93
Marshal . WriteIntPtr ( pyType , offset , func ) ;
94
+
93
95
}
94
96
}
95
97
@@ -116,7 +118,9 @@ private static PyObject GetOperatorType()
116
118
{
117
119
// A hack way for getting typeobject.c::slotdefs
118
120
string code = GenerateDummyCode ( ) ;
121
+ // The resulting OperatorMethod class is stored in a PyDict.
119
122
PythonEngine . Exec ( code , null , locals . Handle ) ;
123
+ // Return the class itself, which is a type.
120
124
return locals . GetItem ( "OperatorMethod" ) ;
121
125
}
122
126
}