Browse Source

Added experimental destructors/finalizers support.

This has exposed some underlying bugs on some pieces of generated code, so I've put it under an option temporarily.

Fixes #148.
pull/153/merge
triton 12 years ago
parent
commit
0f76dc0090
  1. 54
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  2. 48
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  3. 2
      src/Generator/Generators/CLI/CLITextTemplate.cs
  4. 40
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  5. 7
      src/Generator/Options.cs
  6. 5
      tests/Basic/Basic.h

54
src/Generator/Generators/CLI/CLIHeadersTemplate.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators.CSharp;
using CppSharp.Types;
namespace CppSharp.Generators.CLI
@ -252,10 +253,8 @@ namespace CppSharp.Generators.CLI @@ -252,10 +253,8 @@ namespace CppSharp.Generators.CLI
var nativeType = string.Format("::{0}*", @class.QualifiedOriginalName);
if (@class.IsRefType)
{
if (CSharpTextTemplate.ShouldGenerateClassNativeField(@class))
GenerateClassNativeField(@class, nativeType);
}
GenerateClassConstructors(@class, nativeType);
@ -279,23 +278,8 @@ namespace CppSharp.Generators.CLI @@ -279,23 +278,8 @@ namespace CppSharp.Generators.CLI
WriteLine("};");
}
internal static bool HasRefBase(Class @class)
{
Class baseClass = null;
if (@class.HasBaseClass)
baseClass = @class.Bases[0].Class;
var hasRefBase = baseClass != null && baseClass.IsRefType
&& !baseClass.Ignore;
return hasRefBase;
}
public void GenerateClassNativeField(Class @class, string nativeType)
{
if (HasRefBase(@class)) return;
WriteLineIndent("property {0} NativePtr;", nativeType);
PushIndent();
@ -380,19 +364,41 @@ namespace CppSharp.Generators.CLI @@ -380,19 +364,41 @@ namespace CppSharp.Generators.CLI
foreach (var ctor in @class.Constructors)
{
if (ctor.IsCopyConstructor || ctor.IsMoveConstructor)
continue;
// Default constructors are not supported in .NET value types.
if (ctor.Parameters.Count == 0 && @class.IsValueType)
if (ASTUtils.CheckIgnoreMethod(ctor))
continue;
GenerateMethod(ctor);
}
if (@class.IsRefType)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
}
PopIndent();
}
private void GenerateClassDestructor(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Destructor);
WriteLine("~{0}();", @class.Name);
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateClassFinalizer(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Finalizer);
WriteLine("!{0}();", @class.Name);
PopBlock(NewLineKind.BeforeNextBlock);
}
public void GenerateClassFields(Class @class)
{
// Handle the case of struct (value-type) inheritance by adding the base
@ -552,7 +558,7 @@ namespace CppSharp.Generators.CLI @@ -552,7 +558,7 @@ namespace CppSharp.Generators.CLI
return true;
}
if (HasRefBase(@class))
if (CSharpTextTemplate.HasRefBase(@class))
Write(" : {0}", QualifiedIdentifier(@class.Bases[0].Class));
else if (@class.IsRefType)
Write(" : ICppInstance");

48
src/Generator/Generators/CLI/CLISourcesTemplate.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.Generators.CSharp;
using CppSharp.Types;
using Type = CppSharp.AST.Type;
@ -134,6 +135,12 @@ namespace CppSharp.Generators.CLI @@ -134,6 +135,12 @@ namespace CppSharp.Generators.CLI
GenerateClassConstructor(@class, isIntPtr: false);
GenerateClassConstructor(@class, isIntPtr: true);
if (@class.IsRefType)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
}
foreach (var method in @class.Methods)
{
if (ASTUtils.CheckIgnoreMethod(method))
@ -142,9 +149,7 @@ namespace CppSharp.Generators.CLI @@ -142,9 +149,7 @@ namespace CppSharp.Generators.CLI
GenerateMethod(method, @class);
}
if (@class.IsRefType)
{
if (!CLIHeadersTemplate.HasRefBase(@class))
if (CSharpTextTemplate.ShouldGenerateClassNativeField(@class))
{
PushBlock(CLIBlockKind.Method);
WriteLine("System::IntPtr {0}::Instance::get()",
@ -163,7 +168,6 @@ namespace CppSharp.Generators.CLI @@ -163,7 +168,6 @@ namespace CppSharp.Generators.CLI
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
}
GenerateClassProperties(@class, @class);
@ -206,6 +210,42 @@ namespace CppSharp.Generators.CLI @@ -206,6 +210,42 @@ namespace CppSharp.Generators.CLI
GenerateProperty(property, realOwner);
}
private void GenerateClassDestructor(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Destructor);
WriteLine("{0}::~{1}()", QualifiedIdentifier(@class), @class.Name);
WriteStartBraceIndent();
if (CSharpTextTemplate.ShouldGenerateClassNativeField(@class))
WriteLine("delete NativePtr;");
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateClassFinalizer(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Finalizer);
WriteLine("{0}::!{1}()", QualifiedIdentifier(@class), @class.Name);
WriteStartBraceIndent();
if (CSharpTextTemplate.ShouldGenerateClassNativeField(@class))
WriteLine("delete NativePtr;");
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateFunctionTemplate(FunctionTemplate template)
{
var printer = TypePrinter;

2
src/Generator/Generators/CLI/CLITextTemplate.cs

@ -43,6 +43,8 @@ namespace CppSharp.Generators.CLI @@ -43,6 +43,8 @@ namespace CppSharp.Generators.CLI
public const int Typedef = BlockKind.LAST + 14;
public const int Variable = BlockKind.LAST + 15;
public const int Template = BlockKind.LAST + 16;
public static int Destructor = BlockKind.LAST + 17;
public static int Finalizer = BlockKind.LAST + 18;
}
/// <summary>

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

@ -96,6 +96,7 @@ namespace CppSharp.Generators.CSharp @@ -96,6 +96,7 @@ namespace CppSharp.Generators.CSharp
public const int VTableDelegate = FIRST + 16;
public const int Region = FIRST + 17;
public const int Interface = FIRST + 18;
public const int Finalizer = FIRST + 19;
}
public class CSharpTextTemplate : Template
@ -703,21 +704,22 @@ namespace CppSharp.Generators.CSharp @@ -703,21 +704,22 @@ namespace CppSharp.Generators.CSharp
WriteCloseBraceIndent();
}
public bool ShouldGenerateClassNativeField(Class @class)
public static bool HasRefBase(Class @class)
{
if (!@class.IsRefType)
return false;
Class baseClass = null;
if (@class.HasBaseClass)
baseClass = @class.Bases[0].Class;
var hasRefBase = baseClass != null && baseClass.IsRefType && !baseClass.Ignore;
var hasRefBase = baseClass != null && baseClass.IsRefType
&& !baseClass.Ignore;
var hasIgnoredBase = baseClass != null && baseClass.Ignore;
return hasRefBase;
}
return !@class.HasBase || !hasRefBase || hasIgnoredBase;
public static bool ShouldGenerateClassNativeField(Class @class)
{
return @class.IsRefType && (!@class.HasBase || !HasRefBase(@class));
}
public void GenerateClassProlog(Class @class)
@ -1657,8 +1659,26 @@ namespace CppSharp.Generators.CSharp @@ -1657,8 +1659,26 @@ namespace CppSharp.Generators.CSharp
}
if (@class.IsRefType)
{
GenerateClassFinalizer(@class);
GenerateDisposeMethods(@class);
}
}
private void GenerateClassFinalizer(Class @class)
{
if (!Options.GenerateFinalizers)
return;
PushBlock(CSharpBlockKind.Finalizer);
WriteLine("~{0}()", @class.Name);
WriteStartBraceIndent();
WriteLine("Dispose(false);");
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateDisposeMethods(Class @class)
{
@ -1682,12 +1702,12 @@ namespace CppSharp.Generators.CSharp @@ -1682,12 +1702,12 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.Method);
if (@class.IsValueType)
{
this.Write("private ");
Write("private ");
}
else
{
this.Write("protected ");
this.Write(hasBaseClass ? "override " : "virtual ");
Write("protected ");
Write(hasBaseClass ? "override " : "virtual ");
}
WriteLine("void Dispose(bool disposing)");

7
src/Generator/Options.cs

@ -89,6 +89,13 @@ namespace CppSharp @@ -89,6 +89,13 @@ namespace CppSharp
public bool GenerateInterfacesForMultipleInheritance;
public bool GenerateProperties;
public bool GenerateInternalImports;
/// <summary>
/// Enable this option to enable generation of finalizers.
/// Works in both CLI and C# backends.
/// </summary>
public bool GenerateFinalizers;
public string IncludePrefix;
public bool WriteOnlyWhenChanged;
public Func<TranslationUnit, string> GenerateName;

5
tests/Basic/Basic.h

@ -244,4 +244,9 @@ struct DLL_API TestMemoryLeaks @@ -244,4 +244,9 @@ struct DLL_API TestMemoryLeaks
TestMemoryLeaks(const char* name) {}
};
// Tests that finalizers are generated
/* CLI: ~TestFinalizers() */
struct DLL_API TestFinalizers
{
};

Loading…
Cancel
Save