/// <summary> /// For the operator methods of a CLR type, set the special slots of the /// corresponding Python type's operator methods. /// </summary> public static void FixupSlots(BorrowedReference pyType, Type clrType) { Debug.Assert(_opType != null); var operatorCandidates = GetOperatorCandidates(clrType); foreach (var method in operatorCandidates) { // We only want to override slots for operators excluding // comparison operators, which are handled by ClassBase.tp_richcompare. if (!OpMethodMap.ContainsKey(method.Name)) { continue; } int offset = OpMethodMap[method.Name].TypeOffset; // Copy the default implementation of e.g. the nb_add slot, // which simply calls __add__ on the type. IntPtr func = Util.ReadIntPtr(_opType !, offset); // Write the slot definition of the target Python type, so // that we can later modify __add___ and it will be called // when used with a Python operator. // https://tenthousandmeters.com/blog/python-behind-the-scenes-6-how-python-object-system-works/ Util.WriteIntPtr(pyType, offset, func); } }
/// <summary> /// For the operator methods of a CLR type, set the special slots of the /// corresponding Python type's operator methods. /// </summary> /// <param name="pyType"></param> /// <param name="clrType"></param> public static void FixupSlots(IntPtr pyType, Type clrType) { const BindingFlags flags = BindingFlags.Public | BindingFlags.Static; Debug.Assert(_opType != null); var staticMethods = clrType.IsEnum ? typeof(EnumOps <>).MakeGenericType(clrType).GetMethods(flags) : clrType.GetMethods(flags); foreach (var method in staticMethods) { // We only want to override slots for operators excluding // comparison operators, which are handled by ClassBase.tp_richcompare. if (!OpMethodMap.ContainsKey(method.Name)) { continue; } int offset = OpMethodMap[method.Name].TypeOffset; // Copy the default implementation of e.g. the nb_add slot, // which simply calls __add__ on the type. IntPtr func = Marshal.ReadIntPtr(_opType.Handle, offset); // Write the slot definition of the target Python type, so // that we can later modify __add___ and it will be called // when used with a Python operator. // https://tenthousandmeters.com/blog/python-behind-the-scenes-6-how-python-object-system-works/ Marshal.WriteIntPtr(pyType, offset, func); } }
public static bool IsOperatorMethod(MethodBase method) { if (!method.IsSpecialName && !method.IsOpsHelper()) { return(false); } return(OpMethodMap.ContainsKey(method.Name) || ComparisonOpMap.ContainsKey(method.Name)); }
public static string GetPyMethodName(string clrName) { if (OpMethodMap.ContainsKey(clrName)) { return(OpMethodMap[clrName].MethodName); } else { return(ComparisonOpMap[clrName]); } }