public virtual IEnumerable <CppTypeInfo> GetVirtualBases() { foreach (var sub in BaseClasses) { foreach (var virt in sub.GetVirtualBases()) { yield return(virt); } if (VirtualBaseAttribute.IsVirtualBaseOf(WrapperType, sub.WrapperType)) { yield return(sub); } } }
protected virtual void AddBase(CppTypeInfo baseType, BaseVirtualMethods location) { if (TypeComplete) { return; } var baseVMethodCount = baseType.virtual_methods.Count; baseType = baseType.Clone(); baseType.IsFinalClass = false; // Since the class completes before getting added to the parent // We need to remove the size we added for any virtual bases foreach (var virt in baseType.GetVirtualBasesDistinct()) { baseType.field_offset_padding_without_vtptr -= virt.native_size_without_padding + virt.FieldOffsetPadding; } // Don't add virtual methods of virtual bases because they're kept in their own VTable bool isVirtualBase = VirtualBaseAttribute.IsVirtualBaseOf(this.WrapperType, baseType.WrapperType); if (!isVirtualBase) { switch (location) { case BaseVirtualMethods.PrependPrimary: for (int i = 0; i < baseVMethodCount; i++) { virtual_methods.Insert(BaseVTableSlots + i, baseType.virtual_methods[i]); } gchandle_offset_delta = baseType.gchandle_offset_delta; BaseVTableSlots += baseVMethodCount; vt_delegate_types.Add(baseVMethodCount); vt_overrides.Add(baseVMethodCount); break; case BaseVirtualMethods.AppendPrimary: for (int i = 0; i < baseVMethodCount; i++) { virtual_methods.Add(baseType.virtual_methods[i]); } gchandle_offset_delta = baseType.gchandle_offset_delta; vt_delegate_types.Add(baseVMethodCount); vt_overrides.Add(baseVMethodCount); break; case BaseVirtualMethods.NewVTable: baseType.IsPrimaryBase = (base_classes.Count == 0); // offset all previously added bases foreach (var previousBase in base_classes) { previousBase.gchandle_offset_delta += baseType.NativeSize; } // offset derived (this) type's gchandle gchandle_offset_delta += baseType.gchandle_offset_delta + IntPtr.Size; baseType.gchandle_offset_delta += CountBases(b => !b.IsPrimaryBase) * IntPtr.Size; // ensure managed override tramps will be regenerated with correct gchandle offset baseType.vt_overrides = new LazyGeneratedList <Delegate>(baseType.virtual_methods.Count, i => Library.Abi.GetManagedOverrideTrampoline(baseType, i)); baseType.VTableOverrides = new ReadOnlyCollection <Delegate>(baseType.vt_overrides); baseType.lazy_vtable = null; break; } field_offset_padding_without_vtptr += baseType.native_size_without_padding + (location == BaseVirtualMethods.NewVTable ? baseType.FieldOffsetPadding : baseType.field_offset_padding_without_vtptr + (baseType.HasVBTable ? IntPtr.Size : 0)); } base_classes.Add(baseType); }