Exemplo n.º 1
0
        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);
                }
            }
        }
Exemplo n.º 2
0
        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);
        }