diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 4b040991..42a1aafa 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -203,9 +203,10 @@ namespace CppSharp.AST } } - public Method GetRootBaseMethod(Method @override) + public Method GetRootBaseMethod(Method @override, bool onlyFirstBase = false) { return (from @base in Bases + where !@base.Class.IsInterface let baseMethod = ( from method in @base.Class.Methods where @@ -216,13 +217,14 @@ namespace CppSharp.AST new ParameterTypeComparer()) select method).FirstOrDefault() let rootBaseMethod = @base.Class.GetRootBaseMethod(@override) ?? baseMethod - where rootBaseMethod != null + where rootBaseMethod != null || onlyFirstBase select rootBaseMethod).FirstOrDefault(); } - public Property GetRootBaseProperty(Property @override) + public Property GetRootBaseProperty(Property @override, bool onlyFirstBase = false) { return (from @base in Bases + where !@base.Class.IsInterface let baseProperty = ( from property in @base.Class.Properties where @@ -232,7 +234,7 @@ namespace CppSharp.AST new ParameterTypeComparer()) select property).FirstOrDefault() let rootBaseProperty = @base.Class.GetRootBaseProperty(@override) ?? baseProperty - where rootBaseProperty != null + where rootBaseProperty != null || onlyFirstBase select rootBaseProperty).FirstOrDefault(); } diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index a7588177..3a9c234e 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -375,21 +375,12 @@ namespace CppSharp.Generators.CSharp Write("interface "); Write("{0}", SafeIdentifier(@class.Name)); - //var needsBase = @class.HasBaseClass && !@class.IsValueType - // && !@class.Bases[0].Class.IsValueType - // && !@class.Bases[0].Class.Ignore; - - //if (needsBase || @class.IsRefType) - // Write(" : "); - - //if (needsBase) - //{ - // var qualifiedBase = QualifiedIdentifier(@class.Bases[0].Class); - // Write("{0}", qualifiedBase); - - // if (@class.IsRefType) - // Write(", "); - //} + if (@class.HasBase) + { + Write(" : {0}", string.Join(", ", + from @base in @class.Bases + select QualifiedIdentifier(@base.Class))); + } NewLine(); WriteStartBraceIndent(); diff --git a/src/Generator/Passes/MultipleInheritancePass.cs b/src/Generator/Passes/MultipleInheritancePass.cs index d6ca1166..0ffe9570 100644 --- a/src/Generator/Passes/MultipleInheritancePass.cs +++ b/src/Generator/Passes/MultipleInheritancePass.cs @@ -27,19 +27,25 @@ namespace CppSharp.Passes var @base = @class.Bases[i].Class; if (@base.IsInterface) continue; - if (@base.CompleteDeclaration != null) - @base = (Class) @base.CompleteDeclaration; - var name = "I" + @base.Name; - var @interface = (interfaces.ContainsKey(@base) - ? interfaces[@base] - : @base.Namespace.Classes.FirstOrDefault(c => c.Name == name)) ?? - GetNewInterface(@class, name, @base); + var @interface = GetInterface(@class, @base, true); @class.Bases[i] = new BaseClassSpecifier { Type = new TagType(@interface) }; } return base.VisitClassDecl(@class); } - private Class GetNewInterface(Class @class, string name, Class @base) + private Class GetInterface(Class @class, Class @base, bool addMembers = false) + { + if (@base.CompleteDeclaration != null) + @base = (Class) @base.CompleteDeclaration; + var name = "I" + @base.Name; + var @interface = (this.interfaces.ContainsKey(@base) + ? this.interfaces[@base] + : @base.Namespace.Classes.FirstOrDefault(c => c.Name == name)) ?? + GetNewInterface(@class, name, @base, addMembers); + return @interface; + } + + private Class GetNewInterface(Class @class, string name, Class @base, bool addMembers = false) { var @interface = new Class { @@ -48,8 +54,27 @@ namespace CppSharp.Passes Access = @base.Access, IsInterface = true }; + @interface.Bases.AddRange( + from b in @base.Bases + let i = GetInterface(@base, b.Class) + select new BaseClassSpecifier { Type = new TagType(i) }); @interface.Methods.AddRange(@base.Methods.Where( m => !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore)); + @interface.Properties.AddRange(@base.Properties.Where(p => !p.Ignore)); + @interface.Events.AddRange(@base.Events); + if (addMembers) + { + ImplementInterfaceMethods(@class, @interface); + ImplementInterfaceProperties(@class, @interface); + if (@base.Bases.All(b => b.Class != @interface)) + @base.Bases.Add(new BaseClassSpecifier { Type = new TagType(@interface) }); + } + interfaces.Add(@base, @interface); + return @interface; + } + + private static void ImplementInterfaceMethods(Class @class, Class @interface) + { foreach (var method in @interface.Methods) { var impl = new Method(method) @@ -58,28 +83,27 @@ namespace CppSharp.Passes IsVirtual = false, IsOverride = false }; - var rootBaseMethod = @class.GetRootBaseMethod(method); + var rootBaseMethod = @class.GetRootBaseMethod(method, true); if (rootBaseMethod != null && !rootBaseMethod.Ignore) impl.Name = @interface.Name + "." + impl.Name; @class.Methods.Add(impl); } - @interface.Properties.AddRange(@base.Properties.Where(p => !p.Ignore)); + foreach (var @base in @interface.Bases) + ImplementInterfaceMethods(@class, @base.Class); + } + + private static void ImplementInterfaceProperties(Class @class, Class @interface) + { foreach (var property in @interface.Properties) { - var impl = new Property(property) - { - Namespace = @class - }; - var rootBaseProperty = @class.GetRootBaseProperty(property); + var impl = new Property(property) { Namespace = @class }; + var rootBaseProperty = @class.GetRootBaseProperty(property, true); if (rootBaseProperty != null && !rootBaseProperty.Ignore) impl.Name = @interface.Name + "." + impl.Name; @class.Properties.Add(impl); } - @interface.Events.AddRange(@base.Events); - if (@base.Bases.All(b => b.Class != @interface)) - @base.Bases.Add(new BaseClassSpecifier { Type = new TagType(@interface) }); - interfaces.Add(@base, @interface); - return @interface; + foreach (var @base in @interface.Bases) + ImplementInterfaceProperties(@class, @base.Class); } } } diff --git a/tests/CSharpTemp/CSharpTemp.cpp b/tests/CSharpTemp/CSharpTemp.cpp index b0882e34..250ba462 100644 --- a/tests/CSharpTemp/CSharpTemp.cpp +++ b/tests/CSharpTemp/CSharpTemp.cpp @@ -31,6 +31,11 @@ const Foo& Bar::operator[](int i) const return m_foo; } +int Qux::farAwayFunc() +{ + return 20; +} + int Bar::method() { return 2; diff --git a/tests/CSharpTemp/CSharpTemp.h b/tests/CSharpTemp/CSharpTemp.h index 001c658c..f23fd473 100644 --- a/tests/CSharpTemp/CSharpTemp.h +++ b/tests/CSharpTemp/CSharpTemp.h @@ -18,7 +18,13 @@ protected: int P; }; -class DLL_API Bar +class DLL_API Qux +{ +public: + int farAwayFunc(); +}; + +class DLL_API Bar : public Qux { public: int method();