Skip to content

Commit 6df5a1f

Browse files
committed
Add comments and remove unused in operatormethod.cs
Also move fixupslots before pytype_ready. Also apply access violation fix in classderived.
1 parent bafe87e commit 6df5a1f

File tree

3 files changed

+26
-17
lines changed

3 files changed

+26
-17
lines changed

src/runtime/classderived.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ internal ClassDerivedObject(Type tp) : base(tp)
6666
public new static void tp_dealloc(IntPtr ob)
6767
{
6868
var self = (CLRObject)GetManagedObject(ob);
69-
69+
// Amos's fix https://github.com/pythonnet/pythonnet/pull/1260#issuecomment-726719595
70+
if (self.tpHandle == IntPtr.Zero)
71+
{
72+
ClassBase.tp_dealloc(ob);
73+
return;
74+
}
7075
// don't let the python GC destroy this object
7176
Runtime.PyObject_GC_UnTrack(self.pyHandle);
7277

src/runtime/operatormethod.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ namespace Python.Runtime
99
{
1010
internal static class OperatorMethod
1111
{
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.
1215
public static Dictionary<string, Tuple<string, int>> OpMethodMap { get; private set; }
1316

14-
private static Dictionary<string, string> _pyOpNames;
1517
private static PyObject _opType;
1618

1719
static OperatorMethod()
@@ -35,12 +37,6 @@ static OperatorMethod()
3537
["op_Modulus"] = Tuple.Create("__mod__", TypeOffset.nb_remainder),
3638
["op_OneComplement"] = Tuple.Create("__invert__", TypeOffset.nb_invert)
3739
};
38-
39-
_pyOpNames = new Dictionary<string, string>();
40-
foreach (string name in OpMethodMap.Keys)
41-
{
42-
_pyOpNames.Add(GetPyMethodName(name), name);
43-
}
4440
}
4541

4642
public static void Initialize()
@@ -62,11 +58,6 @@ public static bool IsOperatorMethod(string methodName)
6258
return OpMethodMap.ContainsKey(methodName);
6359
}
6460

65-
public static bool IsPyOperatorMethod(string pyMethodName)
66-
{
67-
return _pyOpNames.ContainsKey(pyMethodName);
68-
}
69-
7061
public static bool IsOperatorMethod(MethodBase method)
7162
{
7263
if (!method.IsSpecialName)
@@ -75,7 +66,12 @@ public static bool IsOperatorMethod(MethodBase method)
7566
}
7667
return OpMethodMap.ContainsKey(method.Name);
7768
}
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>
7975
public static void FixupSlots(IntPtr pyType, Type clrType)
8076
{
8177
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
@@ -86,10 +82,16 @@ public static void FixupSlots(IntPtr pyType, Type clrType)
8682
{
8783
continue;
8884
}
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.
9188
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/
9293
Marshal.WriteIntPtr(pyType, offset, func);
94+
9395
}
9496
}
9597

@@ -116,7 +118,9 @@ private static PyObject GetOperatorType()
116118
{
117119
// A hack way for getting typeobject.c::slotdefs
118120
string code = GenerateDummyCode();
121+
// The resulting OperatorMethod class is stored in a PyDict.
119122
PythonEngine.Exec(code, null, locals.Handle);
123+
// Return the class itself, which is a type.
120124
return locals.GetItem("OperatorMethod");
121125
}
122126
}

src/runtime/typemanager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
273273
| TypeFlags.HaveGC;
274274
Util.WriteCLong(type, TypeOffset.tp_flags, flags);
275275

276+
OperatorMethod.FixupSlots(type, clrType);
276277
// Leverage followup initialization from the Python runtime. Note
277278
// that the type of the new type must PyType_Type at the time we
278279
// call this, else PyType_Ready will skip some slot initialization.
@@ -281,7 +282,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
281282
{
282283
throw new PythonException();
283284
}
284-
OperatorMethod.FixupSlots(type, clrType);
285285

286286
IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
287287
string mn = clrType.Namespace ?? "";

0 commit comments

Comments
 (0)