Browse Source

Generated internal implementations of abstract classes in a new pass.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/53/head
Dimitar Dobrev 13 years ago
parent
commit
6d2c0eaed8
  1. 1
      src/Generator/Driver.cs
  2. 3
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  3. 59
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  4. 105
      src/Generator/Passes/AbstractImplementationsPass.cs
  5. 4
      src/Generator/Passes/FindSymbolsPass.cs
  6. 18
      src/Generator/Utils/ParameterTypeComparer.cs
  7. 7
      tests/Basic/Basic.h

1
src/Generator/Driver.cs

@ -148,6 +148,7 @@ namespace CppSharp @@ -148,6 +148,7 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
TranslationUnitPasses.AddPass(new CheckFlagEnumsPass());
TranslationUnitPasses.AddPass(new CheckDuplicatedNamesPass());
TranslationUnitPasses.AddPass(new AbstractImplementationsPass());
}
public void ProcessCode()

3
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -252,7 +252,8 @@ namespace CppSharp.Generators.CSharp @@ -252,7 +252,8 @@ namespace CppSharp.Generators.CSharp
instance = instanceName;
}
Context.Return.Write("new {0}({1})", QualifiedIdentifier(@class),
Context.Return.Write("new {0}({1})",
QualifiedIdentifier(@class) + (@class.IsAbstract ? "Internal" : ""),
instance);
return true;

59
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -4,6 +4,7 @@ using System.Globalization; @@ -4,6 +4,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using CppSharp.AST;
using CppSharp.Utils;
using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CSharp
@ -402,9 +403,6 @@ namespace CppSharp.Generators.CSharp @@ -402,9 +403,6 @@ namespace CppSharp.Generators.CSharp
if (method.IsSynthetized)
return;
if (method.IsPure)
return;
if (method.IsProxy)
return;
@ -611,7 +609,22 @@ namespace CppSharp.Generators.CSharp @@ -611,7 +609,22 @@ namespace CppSharp.Generators.CSharp
if (@class.IsUnion)
WriteLine("[StructLayout(LayoutKind.Explicit)]");
Write("public unsafe ");
switch (@class.Access)
{
case AccessSpecifier.Private:
Write("internal ");
break;
case AccessSpecifier.Protected:
Write("protected ");
break;
case AccessSpecifier.Public:
Write("public ");
break;
}
Write("unsafe ");
if (@class.IsAbstract)
Write("abstract ");
if (Options.GeneratePartialClasses)
Write("partial ");
@ -1459,9 +1472,9 @@ namespace CppSharp.Generators.CSharp @@ -1459,9 +1472,9 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.Method);
GenerateDeclarationCommon(method);
Write("public ");
Write(@class.IsAbstract && method.IsConstructor ? "protected " : "public ");
if (method.IsVirtual && !method.IsOverride)
if (method.IsVirtual && !method.IsOverride && !method.IsPure)
Write("virtual ");
var isBuiltinOperator = method.IsOperator &&
@ -1473,6 +1486,9 @@ namespace CppSharp.Generators.CSharp @@ -1473,6 +1486,9 @@ namespace CppSharp.Generators.CSharp
if (method.IsOverride)
Write("override ");
if (method.IsPure)
Write("abstract ");
var functionName = GetFunctionIdentifier(method);
if (method.IsConstructor || method.IsDestructor)
@ -1482,7 +1498,15 @@ namespace CppSharp.Generators.CSharp @@ -1482,7 +1498,15 @@ namespace CppSharp.Generators.CSharp
GenerateMethodParameters(method);
WriteLine(")");
Write(")");
if (method.IsPure)
{
Write(";");
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
NewLine();
if (method.Kind == CXXMethodKind.Constructor)
GenerateClassConstructorBase(@class, method);
@ -1502,6 +1526,10 @@ namespace CppSharp.Generators.CSharp @@ -1502,6 +1526,10 @@ namespace CppSharp.Generators.CSharp
{
GenerateOperator(method, @class);
}
else if (method.IsOverride && method.IsSynthetized)
{
GenerateVirtualTableMethodCall(method, @class);
}
else
{
GenerateInternalFunctionCall(method);
@ -1529,6 +1557,21 @@ namespace CppSharp.Generators.CSharp @@ -1529,6 +1557,21 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateVirtualTableMethodCall(ITypedDecl method, Class @class)
{
WriteLine("void* vtable = *((void**) __Instance.ToPointer());");
int i;
switch (Driver.Options.Abi)
{
case CppAbi.Microsoft:
throw new NotImplementedException();
default:
i = @class.Layout.Layout.Components.FindIndex(m => m.Method == method);
break;
}
WriteLine("void* slot = *((void**) vtable + {0} * sizeof(IntPtr));", i);
}
private void GenerateOperator(Method method, Class @class)
{
if (method.IsSynthetized)
@ -1974,7 +2017,7 @@ namespace CppSharp.Generators.CSharp @@ -1974,7 +2017,7 @@ namespace CppSharp.Generators.CSharp
public void GenerateInternalFunction(Function function)
{
if (!function.IsProcessed || function.ExplicityIgnored)
if (!function.IsProcessed || function.ExplicityIgnored || function.IsPure)
return;
if (function.OriginalFunction != null)

105
src/Generator/Passes/AbstractImplementationsPass.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
using System.Collections.Generic;
using System.Linq;
using CppSharp.AST;
using CppSharp.Utils;
namespace CppSharp.Passes
{
public class AbstractImplementationsPass : TranslationUnitPass
{
private readonly List<Class> classes = new List<Class>();
public override bool VisitTranslationUnit(TranslationUnit unit)
{
bool result = base.VisitTranslationUnit(unit);
unit.Classes.AddRange(classes);
classes.Clear();
return result;
}
public override bool VisitClassDecl(Class @class)
{
if (@class.CompleteDeclaration != null)
return VisitClassDecl(@class.CompleteDeclaration as Class);
if (!VisitDeclaration(@class) || AlreadyVisited(@class))
return false;
if (@class.IsAbstract)
@classes.Add(AddInternalImplementation(@class));
return base.VisitClassDecl(@class);
}
private static Class AddInternalImplementation(Class @class)
{
var internalImplementation = new Class();
internalImplementation.Name = @class.Name + "Internal";
internalImplementation.Access = AccessSpecifier.Private;
internalImplementation.Namespace = @class.Namespace;
var @base = new BaseClassSpecifier { Type = new TagType(@class) };
internalImplementation.Bases.Add(@base);
var abstractMethods = GetAbstractMethods(@class);
var overriddenMethods = GetOverriddenMethods(@class);
var parameterTypeComparer = new ParameterTypeComparer();
for (int i = abstractMethods.Count - 1; i >= 0; i--)
{
Method @abstract = abstractMethods[i];
if (overriddenMethods.Find(m => m.Name == @abstract.Name &&
m.ReturnType.Type == @abstract.ReturnType.Type &&
m.Parameters.Count == @abstract.Parameters.Count &&
m.Parameters.SequenceEqual(@abstract.Parameters, parameterTypeComparer)) != null)
{
abstractMethods.RemoveAt(i);
}
}
internalImplementation.Methods.AddRange(from abstractMethod in abstractMethods
select new Method(abstractMethod));
internalImplementation.Layout = new ClassLayout(@class.Layout);
var vTableComponents = GetVTableComponents(@class);
for (int i = 0; i < abstractMethods.Count; i++)
{
var vTableComponent = vTableComponents.Find(v => v.Method == abstractMethods[i]);
VTableComponent copy = new VTableComponent();
copy.Kind = vTableComponent.Kind;
copy.Offset = vTableComponent.Offset;
copy.Declaration = internalImplementation.Methods[i];
vTableComponents[vTableComponents.IndexOf(vTableComponent)] = copy;
}
internalImplementation.Layout.Layout.Components.Clear();
internalImplementation.Layout.Layout.Components.AddRange(vTableComponents);
internalImplementation.Layout.VFTables.AddRange(@class.Layout.VFTables);
foreach (Method method in internalImplementation.Methods)
{
method.IsPure = false;
method.IsOverride = true;
method.IsSynthetized = true;
}
return internalImplementation;
}
private static List<Method> GetAbstractMethods(Class @class)
{
var abstractMethods = @class.Methods.Where(m => m.IsPure).ToList();
foreach (BaseClassSpecifier @base in @class.Bases)
abstractMethods.AddRange(GetAbstractMethods(@base.Class));
return abstractMethods;
}
private static List<Method> GetOverriddenMethods(Class @class)
{
var abstractMethods = @class.Methods.Where(m => m.IsOverride).ToList();
foreach (BaseClassSpecifier @base in @class.Bases)
abstractMethods.AddRange(GetOverriddenMethods(@base.Class));
return abstractMethods;
}
private static List<VTableComponent> GetVTableComponents(Class @class)
{
List<VTableComponent> vTableComponents = new List<VTableComponent>(
@class.Layout.Layout.Components);
foreach (BaseClassSpecifier @base in @class.Bases)
vTableComponents.AddRange(GetVTableComponents(@base.Class));
return vTableComponents;
}
}
}

4
src/Generator/Passes/FindSymbolsPass.cs

@ -11,7 +11,9 @@ namespace CppSharp.Passes @@ -11,7 +11,9 @@ namespace CppSharp.Passes
return false;
var mangledDecl = decl as IMangledDecl;
if (mangledDecl != null && !VisitMangledDeclaration(mangledDecl))
var method = decl as Method;
if (mangledDecl != null && !(method != null && method.IsPure) &&
!VisitMangledDeclaration(mangledDecl))
{
decl.ExplicityIgnored = true;
return false;

18
src/Generator/Utils/ParameterTypeComparer.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
using System.Collections.Generic;
using CppSharp.AST;
namespace CppSharp.Utils
{
public class ParameterTypeComparer : IEqualityComparer<Parameter>
{
public bool Equals(Parameter x, Parameter y)
{
return x.Type == y.Type;
}
public int GetHashCode(Parameter obj)
{
return obj.Type.GetHashCode();
}
}
}

7
tests/Basic/Basic.h

@ -80,6 +80,13 @@ public: @@ -80,6 +80,13 @@ public:
Hello* RetNull();
};
class DLL_API AbstractFoo
{
public:
virtual void pureFunction() = 0;
};
DLL_API Bar operator-(const Bar &);
DLL_API Bar operator+(const Bar &, const Bar &);

Loading…
Cancel
Save