diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index 9239a453..4b5b8d44 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -52,8 +52,8 @@ namespace CppSharp.Generators.CLI public void GenerateIncludeForwardRefs() { - var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, - Driver.Options); + var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, + Driver.Options); typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false); var includes = new SortedSet(StringComparer.InvariantCulture); @@ -68,8 +68,8 @@ namespace CppSharp.Generators.CLI var include = typeRef.Include; var unit = include.TranslationUnit; - - if (unit != null && !unit.IsDeclared) + + if (unit != null && !unit.IsDeclared) continue; if(!string.IsNullOrEmpty(include.File) && include.InHeader) @@ -130,8 +130,8 @@ namespace CppSharp.Generators.CLI public void GenerateForwardRefs() { - var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, - Driver.Options); + var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, + Driver.Options); typeReferenceCollector.Process(TranslationUnit); var typeReferences = typeReferenceCollector.TypeReferences; @@ -151,7 +151,7 @@ namespace CppSharp.Generators.CLI // Generate all the enum declarations for the module. foreach (var @enum in decl.Enums) { - if (!@enum.IsGenerated || @enum.IsIncomplete) + if (!@enum.IsGenerated || @enum.IsIncomplete) continue; PushBlock(CLIBlockKind.Enum, @enum); @@ -165,7 +165,7 @@ namespace CppSharp.Generators.CLI // Generate all the struct/class declarations for the module. foreach (var @class in decl.Classes) { - if (!@class.IsGenerated || @class.IsIncomplete) + if (!@class.IsGenerated || @class.IsIncomplete) continue; if (@class.IsOpaque) @@ -210,7 +210,7 @@ namespace CppSharp.Generators.CLI { foreach (var typedef in decl.Typedefs) { - if (!typedef.IsGenerated) + if (!typedef.IsGenerated) continue; GenerateTypedef(typedef); @@ -221,7 +221,7 @@ namespace CppSharp.Generators.CLI { PushBlock(CLIBlockKind.FunctionsClass); - WriteLine("public ref class {0}", TranslationUnit.FileNameWithoutExtension); + WriteLine("public ref class {0}", TranslationUnit.FileNameWithoutExtension); WriteLine("{"); WriteLine("public:"); PushIndent(); @@ -240,7 +240,7 @@ namespace CppSharp.Generators.CLI public void GenerateClass(Class @class) { - if (!@class.IsGenerated || @class.IsIncomplete) + if (!@class.IsGenerated || @class.IsIncomplete) return; GenerateDeclarationCommon(@class); @@ -270,15 +270,15 @@ namespace CppSharp.Generators.CLI GenerateClassVariables(@class); - PushBlock(CLIBlockKind.AccessSpecifier); - WriteLine("private:"); - var accBlock = PopBlock(NewLineKind.IfNotEmpty); + PushBlock(CLIBlockKind.AccessSpecifier); + WriteLine("private:"); + var accBlock = PopBlock(NewLineKind.IfNotEmpty); + + PushBlock(CLIBlockKind.Fields); + GenerateClassFields(@class); + var fieldsBlock = PopBlock(); - PushBlock(CLIBlockKind.Fields); - GenerateClassFields(@class); - var fieldsBlock = PopBlock(); - - accBlock.CheckGenerate = () => !fieldsBlock.IsEmpty; + accBlock.CheckGenerate = () => !fieldsBlock.IsEmpty; WriteLine("};"); } @@ -306,7 +306,7 @@ namespace CppSharp.Generators.CLI PushIndent(); foreach (var template in @class.Templates) { - if (!template.IsGenerated) continue; + if (!template.IsGenerated) continue; var functionTemplate = template as FunctionTemplate; if (functionTemplate == null) continue; @@ -371,7 +371,7 @@ namespace CppSharp.Generators.CLI WriteLine("{0}({1} native);", @class.Name, "System::IntPtr"); foreach (var ctor in @class.Constructors) - { + { if (ASTUtils.CheckIgnoreMethod(ctor, Options)) continue; @@ -382,10 +382,15 @@ namespace CppSharp.Generators.CLI GenerateMethod(ctor); } - if (@class.IsRefType) + if (Options.GenerateFinalizers && @class.IsRefType) { - GenerateClassDestructor(@class); - GenerateClassFinalizer(@class); + var destructor = @class.Destructors + .FirstOrDefault(d => d.Parameters.Count == 0 && d.Access == AccessSpecifier.Public); + if (destructor != null) + { + GenerateClassDestructor(@class); + GenerateClassFinalizer(@class); + } } PopIndent(); @@ -393,9 +398,6 @@ namespace CppSharp.Generators.CLI private void GenerateClassDestructor(Class @class) { - if (!Options.GenerateFinalizers) - return; - PushBlock(CLIBlockKind.Destructor); WriteLine("~{0}();", @class.Name); PopBlock(NewLineKind.BeforeNextBlock); @@ -403,9 +405,6 @@ namespace CppSharp.Generators.CLI private void GenerateClassFinalizer(Class @class) { - if (!Options.GenerateFinalizers) - return; - PushBlock(CLIBlockKind.Finalizer); WriteLine("!{0}();", @class.Name); PopBlock(NewLineKind.BeforeNextBlock); @@ -415,7 +414,7 @@ namespace CppSharp.Generators.CLI { // Handle the case of struct (value-type) inheritance by adding the base // 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)) { @@ -447,14 +446,14 @@ namespace CppSharp.Generators.CLI field.Offset); WriteLine("{0} {1};", field.Type, field.Name); - PopBlock(); + PopBlock(); } public void GenerateClassEvents(Class @class) { foreach (var @event in @class.Events) { - if (!@event.IsGenerated) continue; + if (!@event.IsGenerated) continue; var cppTypePrinter = new CppTypePrinter(Driver.TypeDatabase); var cppArgs = cppTypePrinter.VisitParameters(@event.Parameters, hasNames: true); @@ -494,7 +493,7 @@ namespace CppSharp.Generators.CLI var staticMethods = new List(); foreach (var method in @class.Methods) - { + { if (ASTUtils.CheckIgnoreMethod(method, Options)) continue; @@ -522,7 +521,7 @@ namespace CppSharp.Generators.CLI foreach(var variable in @class.Variables) { - if (!variable.IsGenerated) continue; + if (!variable.IsGenerated) continue; if (variable.Access != AccessSpecifier.Public) continue; @@ -590,7 +589,7 @@ namespace CppSharp.Generators.CLI { // Handle the case of struct (value-type) inheritance by adding the base // 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)) { @@ -615,18 +614,18 @@ namespace CppSharp.Generators.CLI public void GenerateIndexer(Property property) { - var type = property.QualifiedType.Visit(TypePrinter); - var getter = property.GetMethod; - var indexParameter = getter.Parameters[0]; + var type = property.QualifiedType.Visit(TypePrinter); + var getter = property.GetMethod; + var indexParameter = getter.Parameters[0]; var indexParameterType = indexParameter.QualifiedType.Visit(TypePrinter); WriteLine("property {0} default[{1}]", type, indexParameterType); WriteStartBraceIndent(); - if (property.HasGetter) + if (property.HasGetter) 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); WriteCloseBraceIndent(); @@ -638,9 +637,9 @@ namespace CppSharp.Generators.CLI return; PushBlock(CLIBlockKind.Property, property); - var type = property.QualifiedType.Visit(TypePrinter); - - if (property.IsStatic) + var type = property.QualifiedType.Visit(TypePrinter); + + if (property.IsStatic) Write("static "); if (property.IsIndexer) @@ -679,9 +678,9 @@ namespace CppSharp.Generators.CLI Operators.IsBuiltinOperator(method.OperatorKind); if (method.IsStatic || isBuiltinOperator) - Write("static "); - - if (method.OperatorKind == CXXOperatorKind.ExplicitConversion) + Write("static "); + + if (method.OperatorKind == CXXOperatorKind.ExplicitConversion) Write("explicit "); if (method.IsConstructor || method.IsDestructor || @@ -705,7 +704,7 @@ namespace CppSharp.Generators.CLI public bool GenerateTypedef(TypedefDecl typedef) { - if (!typedef.IsGenerated) + if (!typedef.IsGenerated) return false; FunctionType function; @@ -714,20 +713,20 @@ namespace CppSharp.Generators.CLI PushBlock(CLIBlockKind.Typedef, typedef); GenerateDeclarationCommon(typedef); - var insideClass = typedef.Namespace is Class; - - var attributedType = typedef.Type.GetPointee() as AttributedType; - if (attributedType != null) - { - var equivalentFunctionType = attributedType.Equivalent.Type as FunctionType; - var callingConvention = equivalentFunctionType.CallingConvention.ToInteropCallConv(); - if (callingConvention != System.Runtime.InteropServices.CallingConvention.Winapi) - { - WriteLine("[{0}({1}::{2})] ", - "System::Runtime::InteropServices::UnmanagedFunctionPointer", - "System::Runtime::InteropServices::CallingConvention", - callingConvention); - } + var insideClass = typedef.Namespace is Class; + + var attributedType = typedef.Type.GetPointee() as AttributedType; + if (attributedType != null) + { + var equivalentFunctionType = attributedType.Equivalent.Type as FunctionType; + var callingConvention = equivalentFunctionType.CallingConvention.ToInteropCallConv(); + if (callingConvention != System.Runtime.InteropServices.CallingConvention.Winapi) + { + WriteLine("[{0}({1}::{2})] ", + "System::Runtime::InteropServices::UnmanagedFunctionPointer", + "System::Runtime::InteropServices::CallingConvention", + callingConvention); + } } WriteLine("{0}{1};", @@ -744,7 +743,7 @@ namespace CppSharp.Generators.CLI public void GenerateFunction(Function function) { - if (!function.IsGenerated) + if (!function.IsGenerated) return; PushBlock(CLIBlockKind.Function, function); @@ -763,7 +762,7 @@ namespace CppSharp.Generators.CLI public void GenerateEnum(Enumeration @enum) { - if (!@enum.IsGenerated || @enum.IsIncomplete) + if (!@enum.IsGenerated || @enum.IsIncomplete) return; PushBlock(CLIBlockKind.Enum, @enum); diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index 14bb954f..6215dfdd 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -60,7 +60,7 @@ namespace CppSharp.Generators.CLI { PushBlock(CLIBlockKind.IncludesForwardReferences); - var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, Driver.Options); + var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase, Driver.Options); typeReferenceCollector.Process(TranslationUnit, filterNamespaces: false); var includes = new SortedSet(StringComparer.InvariantCulture); @@ -139,7 +139,7 @@ namespace CppSharp.Generators.CLI GenerateClassConstructors(@class); foreach (var method in @class.Methods) - { + { if (ASTUtils.CheckIgnoreMethod(method, Options)) continue; @@ -205,10 +205,15 @@ namespace CppSharp.Generators.CLI GenerateClassConstructor(@class, isIntPtr: false); GenerateClassConstructor(@class, isIntPtr: true); - if (@class.IsRefType) + if (Options.GenerateFinalizers && @class.IsRefType) { - GenerateClassDestructor(@class); - GenerateClassFinalizer(@class); + var destructor = @class.Destructors + .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) { - if (!Options.GenerateFinalizers) - return; - PushBlock(CLIBlockKind.Destructor); WriteLine("{0}::~{1}()", QualifiedIdentifier(@class), @class.Name); @@ -247,9 +249,6 @@ namespace CppSharp.Generators.CLI private void GenerateClassFinalizer(Class @class) { - if (!Options.GenerateFinalizers) - return; - PushBlock(CLIBlockKind.Finalizer); WriteLine("{0}::!{1}()", QualifiedIdentifier(@class), @class.Name); @@ -327,37 +326,37 @@ namespace CppSharp.Generators.CLI GeneratePropertyGetter(property.GetMethod, realOwner, property.Name, property.Type); - if (property.HasSetter) - if (property.IsIndexer) - GeneratePropertySetter(property.SetMethod, realOwner, property.Name, + if (property.HasSetter) + if (property.IsIndexer) + GeneratePropertySetter(property.SetMethod, realOwner, property.Name, property.Type, property.GetMethod.Parameters[0]); - else - GeneratePropertySetter(property.SetMethod, realOwner, property.Name, + else + GeneratePropertySetter(property.SetMethod, realOwner, property.Name, property.Type); } PopBlock(); - } - + } + private void GeneratePropertySetter(T decl, Class @class, string name, Type type, Parameter indexParameter = null) where T : Declaration, ITypedDecl { if (decl == null) - return; - - var args = new List(); - var isIndexer = indexParameter != null; - if (isIndexer) - args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); - - var function = decl as Function; - var argName = function != null && !isIndexer ? function.Parameters[0].Name : "value"; + return; + + var args = new List(); + var isIndexer = indexParameter != null; + if (isIndexer) + args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); + + var function = decl as Function; + var argName = function != null && !isIndexer ? function.Parameters[0].Name : "value"; args.Add(string.Format("{0} {1}", type, argName)); WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class), name, string.Join(", ", args)); - WriteStartBraceIndent(); - + WriteStartBraceIndent(); + if (decl is Function && !isIndexer) { var func = decl as Function; @@ -418,11 +417,11 @@ namespace CppSharp.Generators.CLI var isIndexer = method != null && method.OperatorKind == CXXOperatorKind.Subscript; - var args = new List(); - if (isIndexer) - { - var indexParameter = method.Parameters[0]; - args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); + var args = new List(); + if (isIndexer) + { + var indexParameter = method.Parameters[0]; + args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name)); } 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)) { - GenerateStructMarshaling(@base.Class, nativeVar); + GenerateStructMarshaling(@base.Class, nativeVar); } 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)) { - GenerateValueTypeConstructorCallProperties(@base.Class); + GenerateValueTypeConstructorCallProperties(@base.Class); } foreach (var property in @class.Properties) @@ -811,8 +810,8 @@ namespace CppSharp.Generators.CLI GenerateDeclarationCommon(function); - var classSig = string.Format("{0}::{1}", QualifiedIdentifier(@namespace), - TranslationUnit.FileNameWithoutExtension); + var classSig = string.Format("{0}::{1}", QualifiedIdentifier(@namespace), + TranslationUnit.FileNameWithoutExtension); Write("{0} {1}::{2}(", function.ReturnType, classSig, function.Name); diff --git a/tests/CLITemp/CLITemp.cs b/tests/CLITemp/CLITemp.cs index c8b8b784..4e13a56a 100644 --- a/tests/CLITemp/CLITemp.cs +++ b/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) { } diff --git a/tests/CLITemp/CLITemp.h b/tests/CLITemp/CLITemp.h index 15431f98..de46ecc7 100644 --- a/tests/CLITemp/CLITemp.h +++ b/tests/CLITemp/CLITemp.h @@ -15,3 +15,12 @@ struct DLL_API Types typedef int AttributedFuncType(int, int) ATTR; 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() {} \ No newline at end of file