diff --git a/src/AST/ClassLayout.cs b/src/AST/ClassLayout.cs
index f1a20205..db58cfea 100644
--- a/src/AST/ClassLayout.cs
+++ b/src/AST/ClassLayout.cs
@@ -171,6 +171,11 @@ namespace CppSharp.AST
}
}
+ ///
+ /// Indicates whether this class layout has a subclass at a non-zero offset.
+ ///
+ public bool HasSubclassAtNonZeroOffset { get; set; }
+
private List vTablePointers;
}
}
diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs
index c4e3c73b..04b0fa87 100644
--- a/src/Generator/Generators/CSharp/CSharpSources.cs
+++ b/src/Generator/Generators/CSharp/CSharpSources.cs
@@ -428,7 +428,8 @@ namespace CppSharp.Generators.CSharp
PushBlock(BlockKind.Field);
- WriteLine("protected int {0};", Helpers.PointerAdjustmentIdentifier);
+ if (@class.Layout.HasSubclassAtNonZeroOffset)
+ WriteLine($"protected int {Helpers.PrimaryBaseOffsetIdentifier};");
// use interfaces if any - derived types with a secondary base this class must be compatible with the map
var @interface = @class.Namespace.Classes.FirstOrDefault(
@@ -2183,8 +2184,8 @@ namespace CppSharp.Generators.CSharp
if (@class.IsRefType)
{
- if (@class.HasBaseClass)
- WriteLine("{0} = {1};", Helpers.PointerAdjustmentIdentifier,
+ if (@class.BaseClass?.Layout.HasSubclassAtNonZeroOffset == true)
+ WriteLine("{0} = {1};", Helpers.PrimaryBaseOffsetIdentifier,
GetOffsetToBase(@class, @class.BaseClass));
if (!@class.IsAbstractImpl)
{
@@ -2945,17 +2946,17 @@ namespace CppSharp.Generators.CSharp
to = to.OriginalClass ?? to;
baseOffset = GetOffsetToBase(from, to);
}
- var isPrimaryBase = (from.BaseClass?.OriginalClass ?? from.BaseClass) == to;
- if (isPrimaryBase)
+ bool isPrimaryBase = (from.BaseClass?.OriginalClass ?? from.BaseClass) == to;
+ bool isOrHasSubclassAtNonZeroOffset =
+ from.Layout.HasSubclassAtNonZeroOffset ||
+ to?.Layout.HasSubclassAtNonZeroOffset == true;
+ if (isPrimaryBase && isOrHasSubclassAtNonZeroOffset)
{
- return string.Format("({0} + {1}{2})",
- Helpers.InstanceIdentifier,
- Helpers.PointerAdjustmentIdentifier,
- baseOffset == 0 ? string.Empty : (" - " + baseOffset));
+ return Helpers.InstanceIdentifier +
+ (baseOffset == 0 ? " + " + Helpers.PrimaryBaseOffsetIdentifier : string.Empty);
}
- return string.Format("({0}{1})",
- Helpers.InstanceIdentifier,
- baseOffset == 0 ? string.Empty : " + " + baseOffset);
+ return Helpers.InstanceIdentifier +
+ (baseOffset == 0 ? string.Empty : " + " + baseOffset);
}
private static uint GetOffsetToBase(Class from, Class to)
diff --git a/src/Generator/Generators/CodeGenerator.cs b/src/Generator/Generators/CodeGenerator.cs
index 9257a535..3159ae2d 100644
--- a/src/Generator/Generators/CodeGenerator.cs
+++ b/src/Generator/Generators/CodeGenerator.cs
@@ -1209,7 +1209,7 @@ namespace CppSharp.Generators
public static readonly string InternalStruct = Generator.GeneratedIdentifier("Internal");
public static readonly string InstanceField = Generator.GeneratedIdentifier("instance");
public static readonly string InstanceIdentifier = Generator.GeneratedIdentifier("Instance");
- public static readonly string PointerAdjustmentIdentifier = Generator.GeneratedIdentifier("PointerAdjustment");
+ public static readonly string PrimaryBaseOffsetIdentifier = Generator.GeneratedIdentifier("PrimaryBaseOffset");
public static readonly string ReturnIdentifier = Generator.GeneratedIdentifier("ret");
public static readonly string DummyIdentifier = Generator.GeneratedIdentifier("dummy");
public static readonly string TargetIdentifier = Generator.GeneratedIdentifier("target");
diff --git a/src/Parser/ASTConverter.cs b/src/Parser/ASTConverter.cs
index 21519af3..4e0c3f45 100644
--- a/src/Parser/ASTConverter.cs
+++ b/src/Parser/ASTConverter.cs
@@ -1587,7 +1587,15 @@ namespace CppSharp
_class.IsInjected = @class.IsInjected;
if (@class.Layout != null)
+ {
_class.Layout = VisitClassLayout(@class.Layout);
+ if (_class.BaseClass != null)
+ {
+ AST.LayoutBase @base = _class.Layout.Bases.Find(
+ b => b.Class == _class.BaseClass);
+ _class.BaseClass.Layout.HasSubclassAtNonZeroOffset = @base.Offset > 0;
+ }
+ }
}
public override AST.Declaration VisitClass(Class @class)