From b47fa98c94a2ee8ee1261d583c35afd3ad313d87 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 13 Dec 2013 20:27:14 +0200 Subject: [PATCH] Fixed a regression when marshalling arrays. Migrated the C++/CLI back-end to property usage. Signed-off-by: Dimitar Dobrev --- .../Generators/CLI/CLIHeadersTemplate.cs | 40 +++++++--- src/Generator/Generators/CLI/CLIMarshal.cs | 53 +++++++++---- .../Generators/CLI/CLISourcesTemplate.cs | 78 +++++++++++++------ .../Generators/CSharp/CSharpTextTemplate.cs | 11 +-- src/Generator/Passes/FieldToPropertyPass.cs | 7 +- 5 files changed, 132 insertions(+), 57 deletions(-) diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index 028fcd59..5144026f 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -259,8 +259,6 @@ namespace CppSharp.Generators.CLI GenerateClassConstructors(@class, nativeType); - GenerateClassFields(@class); - GenerateClassProperties(@class); GenerateClassEvents(@class); @@ -271,6 +269,13 @@ namespace CppSharp.Generators.CLI GenerateClassVariables(@class); + if (@class.Fields.Any()) + { + NewLine(); + WriteLine("private:"); + GenerateClassFields(@class); + } + WriteLine("};"); } @@ -390,17 +395,14 @@ namespace CppSharp.Generators.CLI public void GenerateClassFields(Class @class) { - if (!@class.IsValueType) - return; - // Handle the case of struct (value-type) inheritance by adding the base // fields to the managed value subtypes. foreach (var @base in @class.Bases) { - Class baseClass; - if (!@base.Type.IsTagDecl(out baseClass)) + if (!@base.IsClass) continue; + Class baseClass = @base.Class; if (!baseClass.IsValueType || baseClass.Ignore) { Log.EmitMessage("Ignored base class of value type '{0}'", @@ -414,7 +416,7 @@ namespace CppSharp.Generators.CLI PushIndent(); foreach (var field in @class.Fields) { - if (ASTUtils.CheckIgnoreField(field)) continue; + if (ASTUtils.CheckIgnoreField(field) && !@class.IsValueType) continue; GenerateDeclarationCommon(field); if (@class.IsUnion) @@ -558,12 +560,30 @@ namespace CppSharp.Generators.CLI return false; } - public void GenerateClassProperties(Class @class) + public void GenerateClassProperties(Class @class, bool onlyFieldProperties = false) { + // Handle the case of struct (value-type) inheritance by adding the base + // fields to the managed value subtypes. + foreach (var @base in @class.Bases) + { + if (!@base.IsClass) + continue; + + Class baseClass = @base.Class; + if (!baseClass.IsValueType || baseClass.Ignore) + { + Log.EmitMessage("Ignored base class of value type '{0}'", + baseClass.Name); + continue; + } + + GenerateClassProperties(baseClass, true); + } + PushIndent(); foreach (var prop in @class.Properties) { - if (prop.Ignore) continue; + if (prop.Ignore || (onlyFieldProperties && prop.Field == null)) continue; GenerateDeclarationCommon(prop); GenerateProperty(prop); diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index c2b44b73..89d17feb 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -196,7 +196,15 @@ namespace CppSharp.Generators.CLI public override bool VisitDeclaration(Declaration decl) { - throw new NotImplementedException(); + TypeMap typeMap; + if (Context.Driver.TypeDatabase.FindTypeMap(decl, out typeMap)) + { + typeMap.Declaration = decl; + typeMap.CLIMarshalToManaged(Context); + return false; + } + + return true; } public override bool VisitClassDecl(Class @class) @@ -530,7 +538,15 @@ namespace CppSharp.Generators.CLI public override bool VisitDeclaration(Declaration decl) { - throw new NotImplementedException(); + TypeMap typeMap; + if (Context.Driver.TypeDatabase.FindTypeMap(decl, out typeMap)) + { + typeMap.Declaration = decl; + typeMap.CLIMarshalToNative(Context); + return false; + } + + return true; } public override bool VisitClassDecl(Class @class) @@ -589,7 +605,7 @@ namespace CppSharp.Generators.CLI Context.SupportBefore.WriteLine("auto {0} = ::{1}();", marshalVar, @class.QualifiedOriginalName); - MarshalValueClassFields(@class, marshalVar); + MarshalValueClassProperties(@class, marshalVar); Context.Return.Write(marshalVar); @@ -601,7 +617,7 @@ namespace CppSharp.Generators.CLI ArgumentPrefix.Write("&"); } - public void MarshalValueClassFields(Class @class, string marshalVar) + public void MarshalValueClassProperties(Class @class, string marshalVar) { foreach (var @base in @class.Bases) { @@ -609,22 +625,22 @@ namespace CppSharp.Generators.CLI continue; var baseClass = @base.Class; - MarshalValueClassFields(baseClass, marshalVar); + MarshalValueClassProperties(baseClass, marshalVar); } - foreach (var field in @class.Fields) + foreach (var property in @class.Properties) { - if(field.Ignore) + if (property.Ignore || property.Field == null) continue; - MarshalValueClassField(field, marshalVar); + MarshalValueClassProperty(property, marshalVar); } } - private void MarshalValueClassField(Field field, string marshalVar) + private void MarshalValueClassProperty(Property property, string marshalVar) { var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name, - field.Name); + property.Name); var marshalCtx = new MarshalContext(Context.Driver) { @@ -634,7 +650,7 @@ namespace CppSharp.Generators.CLI }; var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx); - field.Visit(marshal); + property.Visit(marshal); Context.ParameterIndex = marshalCtx.ParameterIndex; @@ -643,7 +659,7 @@ namespace CppSharp.Generators.CLI Type type; Class @class; - var isRef = field.Type.IsPointerTo(out type) && + var isRef = property.Type.IsPointerTo(out type) && !(type.IsTagDecl(out @class) && @class.IsValueType) && !type.IsPrimitiveType(); @@ -654,7 +670,7 @@ namespace CppSharp.Generators.CLI } Context.SupportBefore.WriteLine("{0}.{1} = {2};", marshalVar, - field.OriginalName, marshal.Context.Return); + property.Field.OriginalName, marshal.Context.Return); if (isRef) Context.SupportBefore.PopIndent(); @@ -671,6 +687,17 @@ namespace CppSharp.Generators.CLI return field.Type.Visit(this); } + public override bool VisitProperty(Property property) + { + Context.Parameter = new Parameter + { + Name = Context.ArgName, + QualifiedType = property.QualifiedType + }; + + return base.VisitProperty(property); + } + public override bool VisitFunctionDecl(Function function) { throw new NotImplementedException(); diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index a1cb9fa1..51b9e445 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -165,8 +165,7 @@ namespace CppSharp.Generators.CLI } } - foreach (var property in @class.Properties) - GenerateProperty(property); + GenerateClassProperties(@class, @class); foreach (var @event in @class.Events) { @@ -192,6 +191,22 @@ namespace CppSharp.Generators.CLI PopBlock(); } + private void GenerateClassProperties(Class @class, Class realOwner, + bool onlyFieldProperties = false) + { + if (@class.IsValueType) + { + foreach (var @base in @class.Bases.Where(b => b.IsClass && !b.Class.Ignore)) + { + GenerateClassProperties(@base.Class, realOwner, true); + } + } + + foreach (var property in @class.Properties.Where( + p => !p.Ignore && (!onlyFieldProperties || p.Field != null))) + GenerateProperty(property, realOwner); + } + private void GenerateFunctionTemplate(FunctionTemplate template) { var printer = TypePrinter; @@ -236,7 +251,7 @@ namespace CppSharp.Generators.CLI printer.Context = oldCtx; } - private void GenerateProperty(Property property) + private void GenerateProperty(Property property, Class realOwner) { if (property.Ignore) return; @@ -246,21 +261,21 @@ namespace CppSharp.Generators.CLI if (property.Field != null) { if (property.HasGetter) - GeneratePropertyGetter(property.Field, @class, property.Name, + GeneratePropertyGetter(property.Field, realOwner, property.Name, property.Type); if (property.HasSetter) - GeneratePropertySetter(property.Field, @class, property.Name, + GeneratePropertySetter(property.Field, realOwner, property.Name, property.Type); } else { if (property.HasGetter) - GeneratePropertyGetter(property.GetMethod, @class, property.Name, + GeneratePropertyGetter(property.GetMethod, realOwner, property.Name, property.Type); if (property.HasSetter) - GeneratePropertySetter(property.SetMethod, @class, property.Name, + GeneratePropertySetter(property.SetMethod, realOwner, property.Name, property.Type); } PopBlock(); @@ -285,6 +300,13 @@ namespace CppSharp.Generators.CLI } else { + if (@class.IsValueType && decl is Field) + { + WriteLine("{0} = value;", decl.Name); + WriteCloseBraceIndent(); + NewLine(); + return; + } var param = new Parameter { Name = "value", @@ -335,6 +357,13 @@ namespace CppSharp.Generators.CLI } else { + if (@class.IsValueType && decl is Field) + { + WriteLine("return {0};", decl.Name); + WriteCloseBraceIndent(); + NewLine(); + return; + } string variable; if (decl is Variable) variable = string.Format("::{0}::{1}", @@ -526,27 +555,28 @@ namespace CppSharp.Generators.CLI GenerateStructMarshaling(baseClass, nativeVar); } - foreach (var field in @class.Fields) + foreach (var property in @class.Properties) { - if (ASTUtils.CheckIgnoreField(field)) continue; + if (property.Ignore || property.Field == null) continue; var nativeField = string.Format("{0}{1}", - nativeVar, field.OriginalName); + nativeVar, property.Field.OriginalName); var ctx = new MarshalContext(Driver) { - ArgName = field.Name, + ArgName = property.Name, ReturnVarName = nativeField, - ReturnType = field.QualifiedType + ReturnType = property.QualifiedType }; var marshal = new CLIMarshalNativeToManagedPrinter(ctx); - field.Visit(marshal); + property.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) Write(marshal.Context.SupportBefore); - WriteLine("{0} = {1};", field.Name, marshal.Context.Return); + WriteLine("{0} = {1};", + Generator.GeneratedIdentifier(property.Field.OriginalName), marshal.Context.Return); } } @@ -665,10 +695,10 @@ namespace CppSharp.Generators.CLI WriteLine("::{0} _native({1});", @class.QualifiedOriginalName, string.Join(", ", names)); - GenerateValueTypeConstructorCallFields(@class); + GenerateValueTypeConstructorCallProperties(@class); } - private void GenerateValueTypeConstructorCallFields(Class @class) + private void GenerateValueTypeConstructorCallProperties(Class @class) { foreach (var @base in @class.Bases) { @@ -676,28 +706,28 @@ namespace CppSharp.Generators.CLI continue; var baseClass = @base.Class; - GenerateValueTypeConstructorCallFields(baseClass); + GenerateValueTypeConstructorCallProperties(baseClass); } - foreach (var field in @class.Fields) + foreach (var property in @class.Properties) { - if (ASTUtils.CheckIgnoreField(field)) continue; + if (property.Ignore || property.Field == null) continue; - var varName = string.Format("_native.{0}", field.OriginalName); + var varName = string.Format("_native.{0}", property.Field.OriginalName); var ctx = new MarshalContext(Driver) { ReturnVarName = varName, - ReturnType = field.QualifiedType + ReturnType = property.QualifiedType }; var marshal = new CLIMarshalNativeToManagedPrinter(ctx); - field.Visit(marshal); + property.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) Write(marshal.Context.SupportBefore); - WriteLine("this->{0} = {1};", field.Name, marshal.Context.Return); + WriteLine("this->{0} = {1};", property.Name, marshal.Context.Return); } } @@ -749,7 +779,7 @@ namespace CppSharp.Generators.CLI }; var marshal = new CLIMarshalManagedToNativePrinter(ctx); - marshal.MarshalValueClassFields(@class, valueMarshalName); + marshal.MarshalValueClassProperties(@class, valueMarshalName); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) Write(marshal.Context.SupportBefore); diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index fee0ad12..906d78bb 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1108,22 +1108,23 @@ namespace CppSharp.Generators.CSharp } } - private void GenerateClassProperties(Class @class) + private void GenerateClassProperties(Class @class, bool onlyFieldProperties = false) { if (@class.IsValueType) { foreach (var @base in @class.Bases.Where(b => b.IsClass && !b.Class.Ignore)) { - GenerateProperties(@base.Class); + GenerateClassProperties(@base.Class, true); } } - GenerateProperties(@class); + GenerateProperties(@class, onlyFieldProperties); } - private void GenerateProperties(Class @class) + private void GenerateProperties(Class @class, bool onlyFieldProperties = false) { - foreach (var prop in @class.Properties.Where(p => !p.Ignore)) + foreach (var prop in @class.Properties.Where( + p => !p.Ignore && (!onlyFieldProperties || p.Field != null))) { PushBlock(CSharpBlockKind.Property); diff --git a/src/Generator/Passes/FieldToPropertyPass.cs b/src/Generator/Passes/FieldToPropertyPass.cs index ea1374e8..66057cd1 100644 --- a/src/Generator/Passes/FieldToPropertyPass.cs +++ b/src/Generator/Passes/FieldToPropertyPass.cs @@ -20,7 +20,7 @@ namespace CppSharp.Passes // Check if we already have a synthetized property. var existingProp = @class.Properties.FirstOrDefault(property => - property.Name == field.Name && + property.Name == field.Name && property.QualifiedType == field.QualifiedType); if (existingProp != null) @@ -39,10 +39,7 @@ namespace CppSharp.Passes Access = field.Access, Field = field }; - if (@class.IsUnion) - { - field.Name = Generator.GeneratedIdentifier(field.Name); - } + field.Name = Generator.GeneratedIdentifier(field.Name); @class.Properties.Add(prop); @class.Properties.Add(prop);