Beispiel #1
0
        protected virtual void AddBase(CppTypeInfo baseType, BaseVirtualMethods location)
        {
            if (TypeComplete)
            {
                return;
            }

            var baseVMethodCount = baseType.virtual_methods.Count;

            baseType = baseType.Clone();

            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.GCHandleOffset;

                baseType.gchandle_offset_delta += native_size_without_padding + 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;
            }

            base_classes.Add(baseType);

            field_offset_padding_without_vtptr += baseType.native_size_without_padding +
                                                  (location == BaseVirtualMethods.NewVTable? baseType.FieldOffsetPadding : baseType.field_offset_padding_without_vtptr);
        }
Beispiel #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);
        }