Browse Source

Do not generate the destructor/finalizer pair if the destructor of the native class is protected.

Had to fix line endings (LF) in the CLI* files.
pull/237/head
Elias Holzer 11 years ago
parent
commit
6145bf600b
  1. 127
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  2. 75
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  3. 6
      tests/CLITemp/CLITemp.cs
  4. 9
      tests/CLITemp/CLITemp.h

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

@ -52,8 +52,8 @@ namespace CppSharp.Generators.CLI
public void GenerateIncludeForwardRefs() public void GenerateIncludeForwardRefs()
{ {
var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase,
Driver.Options); Driver.Options);
typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false); typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false);
var includes = new SortedSet<string>(StringComparer.InvariantCulture); var includes = new SortedSet<string>(StringComparer.InvariantCulture);
@ -68,8 +68,8 @@ namespace CppSharp.Generators.CLI
var include = typeRef.Include; var include = typeRef.Include;
var unit = include.TranslationUnit; var unit = include.TranslationUnit;
if (unit != null && !unit.IsDeclared) if (unit != null && !unit.IsDeclared)
continue; continue;
if(!string.IsNullOrEmpty(include.File) && include.InHeader) if(!string.IsNullOrEmpty(include.File) && include.InHeader)
@ -130,8 +130,8 @@ namespace CppSharp.Generators.CLI
public void GenerateForwardRefs() public void GenerateForwardRefs()
{ {
var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase,
Driver.Options); Driver.Options);
typeReferenceCollector.Process(TranslationUnit); typeReferenceCollector.Process(TranslationUnit);
var typeReferences = typeReferenceCollector.TypeReferences; var typeReferences = typeReferenceCollector.TypeReferences;
@ -151,7 +151,7 @@ namespace CppSharp.Generators.CLI
// Generate all the enum declarations for the module. // Generate all the enum declarations for the module.
foreach (var @enum in decl.Enums) foreach (var @enum in decl.Enums)
{ {
if (!@enum.IsGenerated || @enum.IsIncomplete) if (!@enum.IsGenerated || @enum.IsIncomplete)
continue; continue;
PushBlock(CLIBlockKind.Enum, @enum); PushBlock(CLIBlockKind.Enum, @enum);
@ -165,7 +165,7 @@ namespace CppSharp.Generators.CLI
// Generate all the struct/class declarations for the module. // Generate all the struct/class declarations for the module.
foreach (var @class in decl.Classes) foreach (var @class in decl.Classes)
{ {
if (!@class.IsGenerated || @class.IsIncomplete) if (!@class.IsGenerated || @class.IsIncomplete)
continue; continue;
if (@class.IsOpaque) if (@class.IsOpaque)
@ -210,7 +210,7 @@ namespace CppSharp.Generators.CLI
{ {
foreach (var typedef in decl.Typedefs) foreach (var typedef in decl.Typedefs)
{ {
if (!typedef.IsGenerated) if (!typedef.IsGenerated)
continue; continue;
GenerateTypedef(typedef); GenerateTypedef(typedef);
@ -221,7 +221,7 @@ namespace CppSharp.Generators.CLI
{ {
PushBlock(CLIBlockKind.FunctionsClass); PushBlock(CLIBlockKind.FunctionsClass);
WriteLine("public ref class {0}", TranslationUnit.FileNameWithoutExtension); WriteLine("public ref class {0}", TranslationUnit.FileNameWithoutExtension);
WriteLine("{"); WriteLine("{");
WriteLine("public:"); WriteLine("public:");
PushIndent(); PushIndent();
@ -240,7 +240,7 @@ namespace CppSharp.Generators.CLI
public void GenerateClass(Class @class) public void GenerateClass(Class @class)
{ {
if (!@class.IsGenerated || @class.IsIncomplete) if (!@class.IsGenerated || @class.IsIncomplete)
return; return;
GenerateDeclarationCommon(@class); GenerateDeclarationCommon(@class);
@ -270,15 +270,15 @@ namespace CppSharp.Generators.CLI
GenerateClassVariables(@class); GenerateClassVariables(@class);
PushBlock(CLIBlockKind.AccessSpecifier); PushBlock(CLIBlockKind.AccessSpecifier);
WriteLine("private:"); WriteLine("private:");
var accBlock = PopBlock(NewLineKind.IfNotEmpty); var accBlock = PopBlock(NewLineKind.IfNotEmpty);
PushBlock(CLIBlockKind.Fields);
GenerateClassFields(@class);
var fieldsBlock = PopBlock();
PushBlock(CLIBlockKind.Fields); accBlock.CheckGenerate = () => !fieldsBlock.IsEmpty;
GenerateClassFields(@class);
var fieldsBlock = PopBlock();
accBlock.CheckGenerate = () => !fieldsBlock.IsEmpty;
WriteLine("};"); WriteLine("};");
} }
@ -306,7 +306,7 @@ namespace CppSharp.Generators.CLI
PushIndent(); PushIndent();
foreach (var template in @class.Templates) foreach (var template in @class.Templates)
{ {
if (!template.IsGenerated) continue; if (!template.IsGenerated) continue;
var functionTemplate = template as FunctionTemplate; var functionTemplate = template as FunctionTemplate;
if (functionTemplate == null) continue; if (functionTemplate == null) continue;
@ -371,7 +371,7 @@ namespace CppSharp.Generators.CLI
WriteLine("{0}({1} native);", @class.Name, "System::IntPtr"); WriteLine("{0}({1} native);", @class.Name, "System::IntPtr");
foreach (var ctor in @class.Constructors) foreach (var ctor in @class.Constructors)
{ {
if (ASTUtils.CheckIgnoreMethod(ctor, Options)) if (ASTUtils.CheckIgnoreMethod(ctor, Options))
continue; continue;
@ -382,10 +382,15 @@ namespace CppSharp.Generators.CLI
GenerateMethod(ctor); GenerateMethod(ctor);
} }
if (@class.IsRefType) if (Options.GenerateFinalizers && @class.IsRefType)
{ {
GenerateClassDestructor(@class); var destructor = @class.Destructors
GenerateClassFinalizer(@class); .FirstOrDefault(d => d.Parameters.Count == 0 && d.Access == AccessSpecifier.Public);
if (destructor != null)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
}
} }
PopIndent(); PopIndent();
@ -393,9 +398,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassDestructor(Class @class) private void GenerateClassDestructor(Class @class)
{ {
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Destructor); PushBlock(CLIBlockKind.Destructor);
WriteLine("~{0}();", @class.Name); WriteLine("~{0}();", @class.Name);
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
@ -403,9 +405,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassFinalizer(Class @class) private void GenerateClassFinalizer(Class @class)
{ {
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Finalizer); PushBlock(CLIBlockKind.Finalizer);
WriteLine("!{0}();", @class.Name); WriteLine("!{0}();", @class.Name);
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
@ -415,7 +414,7 @@ namespace CppSharp.Generators.CLI
{ {
// Handle the case of struct (value-type) inheritance by adding the base // Handle the case of struct (value-type) inheritance by adding the base
// properties to the managed value subtypes. // properties to the managed value subtypes.
if (@class.IsValueType) if (@class.IsValueType)
{ {
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared)) foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared))
{ {
@ -447,14 +446,14 @@ namespace CppSharp.Generators.CLI
field.Offset); field.Offset);
WriteLine("{0} {1};", field.Type, field.Name); WriteLine("{0} {1};", field.Type, field.Name);
PopBlock(); PopBlock();
} }
public void GenerateClassEvents(Class @class) public void GenerateClassEvents(Class @class)
{ {
foreach (var @event in @class.Events) foreach (var @event in @class.Events)
{ {
if (!@event.IsGenerated) continue; if (!@event.IsGenerated) continue;
var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase);
var cppArgs = cppTypePrinter.VisitParameters(@event.Parameters, hasNames: true); var cppArgs = cppTypePrinter.VisitParameters(@event.Parameters, hasNames: true);
@ -494,7 +493,7 @@ namespace CppSharp.Generators.CLI
var staticMethods = new List<Method>(); var staticMethods = new List<Method>();
foreach (var method in @class.Methods) foreach (var method in @class.Methods)
{ {
if (ASTUtils.CheckIgnoreMethod(method, Options)) if (ASTUtils.CheckIgnoreMethod(method, Options))
continue; continue;
@ -522,7 +521,7 @@ namespace CppSharp.Generators.CLI
foreach(var variable in @class.Variables) foreach(var variable in @class.Variables)
{ {
if (!variable.IsGenerated) continue; if (!variable.IsGenerated) continue;
if (variable.Access != AccessSpecifier.Public) if (variable.Access != AccessSpecifier.Public)
continue; continue;
@ -590,7 +589,7 @@ namespace CppSharp.Generators.CLI
{ {
// Handle the case of struct (value-type) inheritance by adding the base // Handle the case of struct (value-type) inheritance by adding the base
// properties to the managed value subtypes. // properties to the managed value subtypes.
if (@class.IsValueType) if (@class.IsValueType)
{ {
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared)) foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared))
{ {
@ -615,18 +614,18 @@ namespace CppSharp.Generators.CLI
public void GenerateIndexer(Property property) public void GenerateIndexer(Property property)
{ {
var type = property.QualifiedType.Visit(TypePrinter); var type = property.QualifiedType.Visit(TypePrinter);
var getter = property.GetMethod; var getter = property.GetMethod;
var indexParameter = getter.Parameters[0]; var indexParameter = getter.Parameters[0];
var indexParameterType = indexParameter.QualifiedType.Visit(TypePrinter); var indexParameterType = indexParameter.QualifiedType.Visit(TypePrinter);
WriteLine("property {0} default[{1}]", type, indexParameterType); WriteLine("property {0} default[{1}]", type, indexParameterType);
WriteStartBraceIndent(); WriteStartBraceIndent();
if (property.HasGetter) if (property.HasGetter)
WriteLine("{0} get({1} {2});", type, indexParameterType, indexParameter.Name); WriteLine("{0} get({1} {2});", type, indexParameterType, indexParameter.Name);
if (property.HasSetter) if (property.HasSetter)
WriteLine("void set({1} {2}, {0} value);", type, indexParameterType, indexParameter.Name); WriteLine("void set({1} {2}, {0} value);", type, indexParameterType, indexParameter.Name);
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -638,9 +637,9 @@ namespace CppSharp.Generators.CLI
return; return;
PushBlock(CLIBlockKind.Property, property); PushBlock(CLIBlockKind.Property, property);
var type = property.QualifiedType.Visit(TypePrinter); var type = property.QualifiedType.Visit(TypePrinter);
if (property.IsStatic) if (property.IsStatic)
Write("static "); Write("static ");
if (property.IsIndexer) if (property.IsIndexer)
@ -679,9 +678,9 @@ namespace CppSharp.Generators.CLI
Operators.IsBuiltinOperator(method.OperatorKind); Operators.IsBuiltinOperator(method.OperatorKind);
if (method.IsStatic || isBuiltinOperator) if (method.IsStatic || isBuiltinOperator)
Write("static "); Write("static ");
if (method.OperatorKind == CXXOperatorKind.ExplicitConversion) if (method.OperatorKind == CXXOperatorKind.ExplicitConversion)
Write("explicit "); Write("explicit ");
if (method.IsConstructor || method.IsDestructor || if (method.IsConstructor || method.IsDestructor ||
@ -705,7 +704,7 @@ namespace CppSharp.Generators.CLI
public bool GenerateTypedef(TypedefDecl typedef) public bool GenerateTypedef(TypedefDecl typedef)
{ {
if (!typedef.IsGenerated) if (!typedef.IsGenerated)
return false; return false;
FunctionType function; FunctionType function;
@ -714,20 +713,20 @@ namespace CppSharp.Generators.CLI
PushBlock(CLIBlockKind.Typedef, typedef); PushBlock(CLIBlockKind.Typedef, typedef);
GenerateDeclarationCommon(typedef); GenerateDeclarationCommon(typedef);
var insideClass = typedef.Namespace is Class; var insideClass = typedef.Namespace is Class;
var attributedType = typedef.Type.GetPointee() as AttributedType; var attributedType = typedef.Type.GetPointee() as AttributedType;
if (attributedType != null) if (attributedType != null)
{ {
var equivalentFunctionType = attributedType.Equivalent.Type as FunctionType; var equivalentFunctionType = attributedType.Equivalent.Type as FunctionType;
var callingConvention = equivalentFunctionType.CallingConvention.ToInteropCallConv(); var callingConvention = equivalentFunctionType.CallingConvention.ToInteropCallConv();
if (callingConvention != System.Runtime.InteropServices.CallingConvention.Winapi) if (callingConvention != System.Runtime.InteropServices.CallingConvention.Winapi)
{ {
WriteLine("[{0}({1}::{2})] ", WriteLine("[{0}({1}::{2})] ",
"System::Runtime::InteropServices::UnmanagedFunctionPointer", "System::Runtime::InteropServices::UnmanagedFunctionPointer",
"System::Runtime::InteropServices::CallingConvention", "System::Runtime::InteropServices::CallingConvention",
callingConvention); callingConvention);
} }
} }
WriteLine("{0}{1};", WriteLine("{0}{1};",
@ -744,7 +743,7 @@ namespace CppSharp.Generators.CLI
public void GenerateFunction(Function function) public void GenerateFunction(Function function)
{ {
if (!function.IsGenerated) if (!function.IsGenerated)
return; return;
PushBlock(CLIBlockKind.Function, function); PushBlock(CLIBlockKind.Function, function);
@ -763,7 +762,7 @@ namespace CppSharp.Generators.CLI
public void GenerateEnum(Enumeration @enum) public void GenerateEnum(Enumeration @enum)
{ {
if (!@enum.IsGenerated || @enum.IsIncomplete) if (!@enum.IsGenerated || @enum.IsIncomplete)
return; return;
PushBlock(CLIBlockKind.Enum, @enum); PushBlock(CLIBlockKind.Enum, @enum);

75
src/Generator/Generators/CLI/CLISourcesTemplate.cs

@ -60,7 +60,7 @@ namespace CppSharp.Generators.CLI
{ {
PushBlock(CLIBlockKind.IncludesForwardReferences); PushBlock(CLIBlockKind.IncludesForwardReferences);
var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, Driver.Options); var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, Driver.Options);
typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false); typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false);
var includes = new SortedSet<string>(StringComparer.InvariantCulture); var includes = new SortedSet<string>(StringComparer.InvariantCulture);
@ -139,7 +139,7 @@ namespace CppSharp.Generators.CLI
GenerateClassConstructors(@class); GenerateClassConstructors(@class);
foreach (var method in @class.Methods) foreach (var method in @class.Methods)
{ {
if (ASTUtils.CheckIgnoreMethod(method, Options)) if (ASTUtils.CheckIgnoreMethod(method, Options))
continue; continue;
@ -205,10 +205,15 @@ namespace CppSharp.Generators.CLI
GenerateClassConstructor(@class, isIntPtr: false); GenerateClassConstructor(@class, isIntPtr: false);
GenerateClassConstructor(@class, isIntPtr: true); GenerateClassConstructor(@class, isIntPtr: true);
if (@class.IsRefType) if (Options.GenerateFinalizers && @class.IsRefType)
{ {
GenerateClassDestructor(@class); var destructor = @class.Destructors
GenerateClassFinalizer(@class); .FirstOrDefault(d => d.Parameters.Count == 0 && d.Access == AccessSpecifier.Public);
if (destructor != null)
{
GenerateClassDestructor(@class);
GenerateClassFinalizer(@class);
}
} }
} }
@ -229,9 +234,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassDestructor(Class @class) private void GenerateClassDestructor(Class @class)
{ {
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Destructor); PushBlock(CLIBlockKind.Destructor);
WriteLine("{0}::~{1}()", QualifiedIdentifier(@class), @class.Name); WriteLine("{0}::~{1}()", QualifiedIdentifier(@class), @class.Name);
@ -247,9 +249,6 @@ namespace CppSharp.Generators.CLI
private void GenerateClassFinalizer(Class @class) private void GenerateClassFinalizer(Class @class)
{ {
if (!Options.GenerateFinalizers)
return;
PushBlock(CLIBlockKind.Finalizer); PushBlock(CLIBlockKind.Finalizer);
WriteLine("{0}::!{1}()", QualifiedIdentifier(@class), @class.Name); WriteLine("{0}::!{1}()", QualifiedIdentifier(@class), @class.Name);
@ -327,37 +326,37 @@ namespace CppSharp.Generators.CLI
GeneratePropertyGetter(property.GetMethod, realOwner, property.Name, GeneratePropertyGetter(property.GetMethod, realOwner, property.Name,
property.Type); property.Type);
if (property.HasSetter) if (property.HasSetter)
if (property.IsIndexer) if (property.IsIndexer)
GeneratePropertySetter(property.SetMethod, realOwner, property.Name, GeneratePropertySetter(property.SetMethod, realOwner, property.Name,
property.Type, property.GetMethod.Parameters[0]); property.Type, property.GetMethod.Parameters[0]);
else else
GeneratePropertySetter(property.SetMethod, realOwner, property.Name, GeneratePropertySetter(property.SetMethod, realOwner, property.Name,
property.Type); property.Type);
} }
PopBlock(); PopBlock();
} }
private void GeneratePropertySetter<T>(T decl, Class @class, string name, Type type, Parameter indexParameter = null) private void GeneratePropertySetter<T>(T decl, Class @class, string name, Type type, Parameter indexParameter = null)
where T : Declaration, ITypedDecl where T : Declaration, ITypedDecl
{ {
if (decl == null) if (decl == null)
return; return;
var args = new List<string>(); var args = new List<string>();
var isIndexer = indexParameter != null; var isIndexer = indexParameter != null;
if (isIndexer) if (isIndexer)
args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name));
var function = decl as Function; var function = decl as Function;
var argName = function != null && !isIndexer ? function.Parameters[0].Name : "value"; var argName = function != null && !isIndexer ? function.Parameters[0].Name : "value";
args.Add(string.Format("{0} {1}", type, argName)); args.Add(string.Format("{0} {1}", type, argName));
WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class), WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class),
name, string.Join(", ", args)); name, string.Join(", ", args));
WriteStartBraceIndent(); WriteStartBraceIndent();
if (decl is Function && !isIndexer) if (decl is Function && !isIndexer)
{ {
var func = decl as Function; var func = decl as Function;
@ -418,11 +417,11 @@ namespace CppSharp.Generators.CLI
var isIndexer = method != null && var isIndexer = method != null &&
method.OperatorKind == CXXOperatorKind.Subscript; method.OperatorKind == CXXOperatorKind.Subscript;
var args = new List<string>(); var args = new List<string>();
if (isIndexer) if (isIndexer)
{ {
var indexParameter = method.Parameters[0]; var indexParameter = method.Parameters[0];
args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name));
} }
WriteLine("{0} {1}::{2}::get({3})", type, QualifiedIdentifier(@class), WriteLine("{0} {1}::{2}::get({3})", type, QualifiedIdentifier(@class),
@ -628,7 +627,7 @@ namespace CppSharp.Generators.CLI
{ {
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared)) foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared))
{ {
GenerateStructMarshaling(@base.Class, nativeVar); GenerateStructMarshaling(@base.Class, nativeVar);
} }
foreach (var property in @class.Properties.Where( p => !ASTUtils.CheckIgnoreProperty(p))) foreach (var property in @class.Properties.Where( p => !ASTUtils.CheckIgnoreProperty(p)))
@ -779,7 +778,7 @@ namespace CppSharp.Generators.CLI
{ {
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared)) foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared))
{ {
GenerateValueTypeConstructorCallProperties(@base.Class); GenerateValueTypeConstructorCallProperties(@base.Class);
} }
foreach (var property in @class.Properties) foreach (var property in @class.Properties)
@ -811,8 +810,8 @@ namespace CppSharp.Generators.CLI
GenerateDeclarationCommon(function); GenerateDeclarationCommon(function);
var classSig = string.Format("{0}::{1}", QualifiedIdentifier(@namespace), var classSig = string.Format("{0}::{1}", QualifiedIdentifier(@namespace),
TranslationUnit.FileNameWithoutExtension); TranslationUnit.FileNameWithoutExtension);
Write("{0} {1}::{2}(", function.ReturnType, classSig, Write("{0} {1}::{2}(", function.ReturnType, classSig,
function.Name); function.Name);

6
tests/CLITemp/CLITemp.cs

@ -11,6 +11,12 @@ namespace CppSharp.Tests
{ {
} }
public override void Setup(Driver driver)
{
driver.Options.GenerateFinalizers = true;
base.Setup(driver);
}
public override void Preprocess(Driver driver, ASTContext ctx) public override void Preprocess(Driver driver, ASTContext ctx)
{ {
} }

9
tests/CLITemp/CLITemp.h

@ -15,3 +15,12 @@ struct DLL_API Types
typedef int AttributedFuncType(int, int) ATTR; typedef int AttributedFuncType(int, int) ATTR;
AttributedFuncType AttributedSum; AttributedFuncType AttributedSum;
}; };
// Tests code generator to not generate a destructor/finalizer pair
// if the destructor of the C++ class is not public.
class DLL_API TestProtectedDestructors
{
~TestProtectedDestructors();
};
TestProtectedDestructors::~TestProtectedDestructors() {}
Loading…
Cancel
Save