/// <summary> /// Helper for InitializeSlots. /// /// Initializes one slot to point to a function pointer. /// The function pointer might be a thunk for C#, or it may be /// an address in the NativeCodePage. /// </summary> /// <param name="type">Type being initialized.</param> /// <param name="slot">Function pointer.</param> /// <param name="name">Name of the method.</param> /// <param name="canOverride">Can override the slot when it existed</param> static void InitializeSlot(IntPtr type, IntPtr slot, string name, bool canOverride = true) { var offset = ManagedDataOffsets.GetSlotOffset(name); if (!canOverride && Marshal.ReadIntPtr(type, offset) != IntPtr.Zero) { return; } Marshal.WriteIntPtr(type, offset, slot); }
static void InitializeSlot(IntPtr type, ThunkInfo thunk, string name, SlotsHolder slotsHolder = null, bool canOverride = true) { int offset = ManagedDataOffsets.GetSlotOffset(name); if (!canOverride && Marshal.ReadIntPtr(type, offset) != IntPtr.Zero) { return; } Marshal.WriteIntPtr(type, offset, thunk.Address); if (slotsHolder != null) { slotsHolder.Set(offset, thunk); } }
/// <summary> /// Given a newly allocated Python type object and a managed Type that /// provides the implementation for the type, connect the type slots of /// the Python object to the managed methods of the implementing Type. /// </summary> internal static void InitializeSlots(IntPtr type, Type impl, SlotsHolder slotsHolder = null) { // We work from the most-derived class up; make sure to get // the most-derived slot and not to override it with a base // class's slot. var seen = new HashSet <string>(); while (impl != null) { MethodInfo[] methods = impl.GetMethods(tbFlags); foreach (MethodInfo method in methods) { string name = method.Name; if (!name.StartsWith("tp_") && !TypeOffset.IsSupportedSlotName(name)) { Debug.Assert(!name.Contains("_") || name.StartsWith("_") || method.IsSpecialName); continue; } if (seen.Contains(name)) { continue; } InitializeSlot(type, Interop.GetThunk(method), name, slotsHolder); seen.Add(name); } impl = impl.BaseType; } foreach (string slot in _requiredSlots) { if (seen.Contains(slot)) { continue; } var offset = ManagedDataOffsets.GetSlotOffset(slot); Marshal.WriteIntPtr(type, offset, SlotsHolder.GetDefaultSlot(offset)); } }
static bool IsSlotSet(IntPtr type, string name) { int offset = ManagedDataOffsets.GetSlotOffset(name); return(Marshal.ReadIntPtr(type, offset) != IntPtr.Zero); }