diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index 182cf11d..c4e3c73b 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -2945,7 +2945,7 @@ namespace CppSharp.Generators.CSharp to = to.OriginalClass ?? to; baseOffset = GetOffsetToBase(from, to); } - var isPrimaryBase = from.BaseClass == to; + var isPrimaryBase = (from.BaseClass?.OriginalClass ?? from.BaseClass) == to; if (isPrimaryBase) { return string.Format("({0} + {1}{2})", diff --git a/src/Generator/Passes/MultipleInheritancePass.cs b/src/Generator/Passes/MultipleInheritancePass.cs index 6fdc4edb..975c73ad 100644 --- a/src/Generator/Passes/MultipleInheritancePass.cs +++ b/src/Generator/Passes/MultipleInheritancePass.cs @@ -15,6 +15,11 @@ namespace CppSharp.Passes /// private readonly HashSet interfaces = new HashSet(); + /// + /// Change and implement secondaryy bases at the end to avoid processing implementations. + /// + private readonly HashSet classesWithSecondaryBases = new HashSet(); + public MultipleInheritancePass() { VisitOptions.VisitClassFields = false; @@ -35,26 +40,40 @@ namespace CppSharp.Passes int index = @interface.Namespace.Declarations.IndexOf(@interface.OriginalClass); @interface.Namespace.Declarations.Insert(index, @interface); } + + foreach (Class @class in classesWithSecondaryBases) + { + for (var i = 1; i < @class.Bases.Count; i++) + { + var @base = @class.Bases[i]; + Class @interface = interfaces.FirstOrDefault(iface => iface.OriginalClass == @base.Class); + if (@interface == null) + continue; + @class.Bases[i] = new BaseClassSpecifier(@base) { Type = new TagType(@interface) }; + ImplementInterfaceMethods(@class, @interface); + ImplementInterfaceProperties(@class, @interface); + } + } + interfaces.Clear(); + classesWithSecondaryBases.Clear(); return result; } public override bool VisitClassDecl(Class @class) { - if (!base.VisitClassDecl(@class) || !@class.IsGenerated) + if (!base.VisitClassDecl(@class) || !@class.IsGenerated || @class.Bases.Count == 1) return false; + classesWithSecondaryBases.Add(@class); + // skip the first base because we can inherit from one class for (var i = 1; i < @class.Bases.Count; i++) { var @base = @class.Bases[i]; var baseClass = @base.Class; if (baseClass == null || baseClass.IsInterface || !baseClass.IsGenerated) continue; - - var @interface = GetInterface(baseClass); - @class.Bases[i] = new BaseClassSpecifier(@base) { Type = new TagType(@interface) }; - ImplementInterfaceMethods(@class, @interface); - ImplementInterfaceProperties(@class, @interface); + GetInterface(baseClass); } return true; } diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index 42f13a7d..f06c4e1f 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -371,13 +371,20 @@ public unsafe class CSharpTests : GeneratorTestFixture [Test] public void TestPrimarySecondaryBase() { - var a = new MI_A0(); - var resa = a.Get(); - Assert.That(resa, Is.EqualTo(50)); + using (var a = new MI_A0()) + { + Assert.That(a.Get(), Is.EqualTo(50)); + } - var c = new MI_C(); - var res = c.Get(); - Assert.That(res, Is.EqualTo(50)); + using (var c = new MI_C()) + { + Assert.That(c.Get(), Is.EqualTo(50)); + } + + using (var d = new MI_D()) + { + Assert.That(d.Get(), Is.EqualTo(50)); + } } [Test] diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index 8df775a5..5a344000 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -580,6 +580,20 @@ struct DLL_API MI_C : public MI_A0, public MI_B MI_C::MI_C() {} +struct DLL_API MI_A1 +{ + MI_A1(); +}; + +MI_A1::MI_A1() {} + +struct DLL_API MI_D : public MI_A1, public MI_C +{ + MI_D(); +}; + +MI_D::MI_D() {} + class DLL_API StructWithPrivateFields { public: