From e43dd1c18f6d0636b311a97b9d3281068032f19f Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 27 Oct 2016 00:26:49 +0300 Subject: [PATCH] Fixed the adjustment of the instance in cases of multiple inheritance. Signed-off-by: Dimitar Dobrev --- .../Generators/CSharp/CSharpSources.cs | 9 +++++++-- .../Passes/MultipleInheritancePass.cs | 13 ++++++++---- tests/CSharp/CSharp.Tests.cs | 2 ++ tests/CSharp/CSharp.cpp | 20 ++++++++++++++++++- tests/CSharp/CSharp.h | 10 +++++++++- 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index ea2ee1b2..c49db501 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -2513,7 +2513,12 @@ namespace CppSharp.Generators.CSharp private void GetVirtualCallDelegate(Method method, Class @class, out string delegateId) { - var i = VTables.GetVTableIndex(method.OriginalFunction ?? method, @class); + Function @virtual = method; + if (method.OriginalFunction != null && + !((Class) method.OriginalFunction.Namespace).IsInterface) + @virtual = method.OriginalFunction; + + var i = VTables.GetVTableIndex(@virtual, @class); int vtableIndex = 0; if (Context.ParserOptions.IsMicrosoftAbi) vtableIndex = @class.Layout.VFTables.IndexOf(@class.Layout.VFTables.Where( @@ -2526,7 +2531,7 @@ namespace CppSharp.Generators.CSharp WriteStartBraceIndent(); } - var @delegate = GetVTableMethodDelegateName(method.OriginalFunction ?? method); + var @delegate = GetVTableMethodDelegateName(@virtual); delegateId = Generator.GeneratedIdentifier(@delegate); WriteLine("var {0} = ({1}) Marshal.GetDelegateForFunctionPointer(new IntPtr({2}), typeof({1}));", diff --git a/src/Generator/Passes/MultipleInheritancePass.cs b/src/Generator/Passes/MultipleInheritancePass.cs index c379e3d3..62f55959 100644 --- a/src/Generator/Passes/MultipleInheritancePass.cs +++ b/src/Generator/Passes/MultipleInheritancePass.cs @@ -164,11 +164,16 @@ namespace CppSharp.Passes { foreach (var method in @interface.Methods) { - if (@class.Methods.Any(m => m.OriginalName == method.OriginalName && - m.Parameters.Where(p => !p.Ignore).SequenceEqual( - method.Parameters.Where(p => !p.Ignore), - ParameterTypeComparer.Instance))) + var existingImpl = @class.Methods.FirstOrDefault( + m => m.OriginalName == method.OriginalName && + m.Parameters.Where(p => !p.Ignore).SequenceEqual( + method.Parameters.Where(p => !p.Ignore), + ParameterTypeComparer.Instance)); + if (existingImpl != null) + { + existingImpl.OriginalFunction = method; continue; + } var impl = new Method(method) { Namespace = @class, diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index 86939716..fa949419 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -647,6 +647,8 @@ public unsafe class CSharpTests : GeneratorTestFixture { Assert.That(implementsAbstractsFromPrimaryAndSecondary.AbstractInPrimaryBase, Is.EqualTo(101)); Assert.That(implementsAbstractsFromPrimaryAndSecondary.AbstractInSecondaryBase, Is.EqualTo(5)); + Assert.That(implementsAbstractsFromPrimaryAndSecondary.AbstractReturnsFieldInPrimaryBase, Is.EqualTo(201)); + Assert.That(implementsAbstractsFromPrimaryAndSecondary.AbstractReturnsFieldInSecondaryBase, Is.EqualTo(202)); } } diff --git a/tests/CSharp/CSharp.cpp b/tests/CSharp/CSharp.cpp index ada200e4..9d9074cb 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/CSharp/CSharp.cpp @@ -1222,7 +1222,15 @@ void HasMissingObjectOnVirtualCall::setMissingObjectOnVirtualCall(MissingObjectO stackOverflowOnVirtualCall = value; } -ImplementsAbstractsFromPrimaryAndSecondary::ImplementsAbstractsFromPrimaryAndSecondary() +AbstractPrimaryBase::~AbstractPrimaryBase() +{ +} + +AbstractSecondaryBase::~AbstractSecondaryBase() +{ +} + +ImplementsAbstractsFromPrimaryAndSecondary::ImplementsAbstractsFromPrimaryAndSecondary() : field(200) { } @@ -1239,3 +1247,13 @@ int ImplementsAbstractsFromPrimaryAndSecondary::abstractInSecondaryBase() { return 5; } + +int ImplementsAbstractsFromPrimaryAndSecondary::abstractReturnsFieldInPrimaryBase() +{ + return field + 1; +} + +int ImplementsAbstractsFromPrimaryAndSecondary::abstractReturnsFieldInSecondaryBase() +{ + return field + 2; +} diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index 910fd8f4..aefbd3a3 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -1095,20 +1095,28 @@ private: class DLL_API AbstractPrimaryBase { public: + virtual ~AbstractPrimaryBase(); virtual int abstractInPrimaryBase() = 0; + virtual int abstractReturnsFieldInPrimaryBase() = 0; }; class DLL_API AbstractSecondaryBase { public: + virtual ~AbstractSecondaryBase(); virtual int abstractInSecondaryBase() = 0; + virtual int abstractReturnsFieldInSecondaryBase() = 0; }; class DLL_API ImplementsAbstractsFromPrimaryAndSecondary : public AbstractPrimaryBase, public AbstractSecondaryBase { public: ImplementsAbstractsFromPrimaryAndSecondary(); - ~ImplementsAbstractsFromPrimaryAndSecondary(); + virtual ~ImplementsAbstractsFromPrimaryAndSecondary(); virtual int abstractInPrimaryBase(); virtual int abstractInSecondaryBase(); + virtual int abstractReturnsFieldInPrimaryBase(); + virtual int abstractReturnsFieldInSecondaryBase(); +private: + int field; };