Browse Source

Fixed the selection of a virtual table to call virtual methods through in the C# generator.

Fixes https://github.com/mono/CppSharp/issues/703.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/719/head
Dimitar Dobrev 9 years ago
parent
commit
924ceaf85a
  1. 8
      src/Generator/Generators/CSharp/CSharpSources.cs
  2. 38
      tests/CSharp/CSharp.Tests.cs
  3. 18
      tests/CSharp/CSharp.cpp
  4. 21
      tests/CSharp/CSharp.h

8
src/Generator/Generators/CSharp/CSharpSources.cs

@ -2515,8 +2515,12 @@ namespace CppSharp.Generators.CSharp
out string delegateId) out string delegateId)
{ {
var i = VTables.GetVTableIndex(method.OriginalFunction ?? method, @class); var i = VTables.GetVTableIndex(method.OriginalFunction ?? method, @class);
WriteLine("var {0} = *(void**) ((IntPtr) __OriginalVTables[0] + {1} * {2});", int vtableIndex = 0;
Helpers.SlotIdentifier, i, Context.TargetInfo.PointerWidth / 8); if (Context.ParserOptions.IsMicrosoftAbi)
vtableIndex = @class.Layout.VFTables.IndexOf(@class.Layout.VFTables.Where(
v => v.Layout.Components.Any(c => c.Method.OriginalPtr == method.OriginalPtr)).First());
WriteLine("var {0} = *(void**) ((IntPtr) __OriginalVTables[{1}] + {2} * {3});",
Helpers.SlotIdentifier, vtableIndex, i, Context.TargetInfo.PointerWidth / 8);
if (method.IsDestructor && @class.IsAbstract) if (method.IsDestructor && @class.IsAbstract)
{ {
WriteLine("if ({0} != null)", Helpers.SlotIdentifier); WriteLine("if ({0} != null)", Helpers.SlotIdentifier);

38
tests/CSharp/CSharp.Tests.cs

@ -627,6 +627,29 @@ public unsafe class CSharpTests : GeneratorTestFixture
} }
} }
[Test]
public void TestStackOverflowOnVirtualCall()
{
using (var hasMissingObjectOnVirtualCall = new HasMissingObjectOnVirtualCall())
{
using (var missingObjectOnVirtualCall = new MissingObjectOnVirtualCall())
{
hasMissingObjectOnVirtualCall.SetMissingObjectOnVirtualCall(missingObjectOnVirtualCall);
hasMissingObjectOnVirtualCall.MakeMissingObjectOnVirtualCall();
}
}
}
[Test]
public void TestAbstractImplementatonsInPrimaryAndSecondaryBases()
{
using (var implementsAbstractsFromPrimaryAndSecondary = new ImplementsAbstractsFromPrimaryAndSecondary())
{
Assert.That(implementsAbstractsFromPrimaryAndSecondary.AbstractInPrimaryBase, Is.EqualTo(101));
Assert.That(implementsAbstractsFromPrimaryAndSecondary.AbstractInSecondaryBase, Is.EqualTo(5));
}
}
private class OverrideVirtualWithString : HasVirtualTakesReturnsProblematicTypes private class OverrideVirtualWithString : HasVirtualTakesReturnsProblematicTypes
{ {
public override string VirtualTakesAndReturnsString(string c) public override string VirtualTakesAndReturnsString(string c)
@ -647,17 +670,4 @@ public unsafe class CSharpTests : GeneratorTestFixture
return base.HasPointerToEnumInParam(pointerToEnum); return base.HasPointerToEnumInParam(pointerToEnum);
} }
} }
}
[Test]
public void TestStackOverflowOnVirtualCall()
{
using (var hasMissingObjectOnVirtualCall = new HasMissingObjectOnVirtualCall())
{
using (var missingObjectOnVirtualCall = new MissingObjectOnVirtualCall())
{
hasMissingObjectOnVirtualCall.SetMissingObjectOnVirtualCall(missingObjectOnVirtualCall);
hasMissingObjectOnVirtualCall.MakeMissingObjectOnVirtualCall();
}
}
}
}

18
tests/CSharp/CSharp.cpp

@ -1221,3 +1221,21 @@ void HasMissingObjectOnVirtualCall::setMissingObjectOnVirtualCall(MissingObjectO
{ {
stackOverflowOnVirtualCall = value; stackOverflowOnVirtualCall = value;
} }
ImplementsAbstractsFromPrimaryAndSecondary::ImplementsAbstractsFromPrimaryAndSecondary()
{
}
ImplementsAbstractsFromPrimaryAndSecondary::~ImplementsAbstractsFromPrimaryAndSecondary()
{
}
int ImplementsAbstractsFromPrimaryAndSecondary::abstractInPrimaryBase()
{
return 101;
}
int ImplementsAbstractsFromPrimaryAndSecondary::abstractInSecondaryBase()
{
return 5;
}

21
tests/CSharp/CSharp.h

@ -1091,3 +1091,24 @@ public:
private: private:
MissingObjectOnVirtualCall* stackOverflowOnVirtualCall; MissingObjectOnVirtualCall* stackOverflowOnVirtualCall;
}; };
class DLL_API AbstractPrimaryBase
{
public:
virtual int abstractInPrimaryBase() = 0;
};
class DLL_API AbstractSecondaryBase
{
public:
virtual int abstractInSecondaryBase() = 0;
};
class DLL_API ImplementsAbstractsFromPrimaryAndSecondary : public AbstractPrimaryBase, public AbstractSecondaryBase
{
public:
ImplementsAbstractsFromPrimaryAndSecondary();
~ImplementsAbstractsFromPrimaryAndSecondary();
virtual int abstractInPrimaryBase();
virtual int abstractInSecondaryBase();
};

Loading…
Cancel
Save