Browse Source

Merge pull request #151 from ddobrev/field_props

Field properties
pull/152/head
João Matos 12 years ago
parent
commit
4f084a09bf
  1. 13
      src/AST/Property.cs
  2. 69
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  3. 53
      src/Generator/Generators/CLI/CLIMarshal.cs
  4. 76
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  5. 14
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  6. 135
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  7. 11
      src/Generator/Passes/FieldToPropertyPass.cs
  8. 1
      src/Generator/Passes/verbs.txt
  9. 16
      tests/Basic/Basic.Tests.cs
  10. 1
      tests/Basic/Basic.h

13
src/AST/Property.cs

@ -104,5 +104,18 @@ namespace CppSharp.AST @@ -104,5 +104,18 @@ namespace CppSharp.AST
{
return visitor.VisitProperty(this);
}
public bool IsBackedByValueClassField()
{
if (Field == null)
return false;
Type type;
Field.Type.IsPointerTo(out type);
type = type ?? Field.Type;
Class decl;
return type.IsTagDecl(out decl) && decl.IsValueType;
}
}
}

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

@ -259,8 +259,6 @@ namespace CppSharp.Generators.CLI @@ -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 @@ -271,6 +269,13 @@ namespace CppSharp.Generators.CLI
GenerateClassVariables(@class);
if (@class.Fields.Any())
{
NewLine();
WriteLine("private:");
GenerateClassFields(@class);
}
WriteLine("};");
}
@ -390,41 +395,43 @@ namespace CppSharp.Generators.CLI @@ -390,41 +395,43 @@ 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.
// properties 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}'",
baseClass.Name);
continue;
}
GenerateClassFields(baseClass);
}
PushIndent();
foreach (var field in @class.Fields)
// check for value types because some of the ignored fields may back properties;
// not the case for ref types because the NativePtr pattern is used there
foreach (var field in @class.Fields.Where(f => !f.Ignore || @class.IsValueType))
{
if (ASTUtils.CheckIgnoreField(field)) continue;
GenerateDeclarationCommon(field);
if (@class.IsUnion)
WriteLine("[System::Runtime::InteropServices::FieldOffset({0})]",
field.Offset);
WriteLine("{0} {1};", field.Type, SafeIdentifier(field.Name));
var property = @class.Properties.FirstOrDefault(p => p.Field == field);
if (property != null && !property.IsBackedByValueClassField())
{
GenerateField(@class, field);
}
}
PopIndent();
}
private void GenerateField(Class @class, Field field)
{
GenerateDeclarationCommon(field);
if (@class.IsUnion)
WriteLine("[System::Runtime::InteropServices::FieldOffset({0})]",
field.Offset);
WriteLine("{0} {1};", field.Type, SafeIdentifier(field.Name));
}
public void GenerateClassEvents(Class @class)
{
foreach (var @event in @class.Events)
@ -560,10 +567,28 @@ namespace CppSharp.Generators.CLI @@ -560,10 +567,28 @@ namespace CppSharp.Generators.CLI
public void GenerateClassProperties(Class @class)
{
// Handle the case of struct (value-type) inheritance by adding the base
// properties to the managed value subtypes.
foreach (var @base in @class.Bases)
{
if (!@base.IsClass)
continue;
Class baseClass = @base.Class;
if (!baseClass.IsValueType || baseClass.Ignore)
continue;
GenerateClassProperties(baseClass);
}
PushIndent();
foreach (var prop in @class.Properties)
foreach (var prop in @class.Properties.Where(prop => !prop.Ignore))
{
if (prop.Ignore) continue;
if (prop.IsBackedByValueClassField())
{
GenerateField(@class, prop.Field);
continue;
}
GenerateDeclarationCommon(prop);
GenerateProperty(prop);

53
src/Generator/Generators/CLI/CLIMarshal.cs

@ -196,7 +196,15 @@ namespace CppSharp.Generators.CLI @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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();

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

@ -165,8 +165,7 @@ namespace CppSharp.Generators.CLI @@ -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,21 @@ namespace CppSharp.Generators.CLI @@ -192,6 +191,21 @@ namespace CppSharp.Generators.CLI
PopBlock();
}
private void GenerateClassProperties(Class @class, Class realOwner)
{
if (@class.IsValueType)
{
foreach (var @base in @class.Bases.Where(b => b.IsClass && !b.Class.Ignore))
{
GenerateClassProperties(@base.Class, realOwner);
}
}
foreach (var property in @class.Properties.Where(
p => !p.Ignore && !p.IsBackedByValueClassField()))
GenerateProperty(property, realOwner);
}
private void GenerateFunctionTemplate(FunctionTemplate template)
{
var printer = TypePrinter;
@ -236,7 +250,7 @@ namespace CppSharp.Generators.CLI @@ -236,7 +250,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 +260,21 @@ namespace CppSharp.Generators.CLI @@ -246,21 +260,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 +299,13 @@ namespace CppSharp.Generators.CLI @@ -285,6 +299,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 +356,13 @@ namespace CppSharp.Generators.CLI @@ -335,6 +356,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 +554,27 @@ namespace CppSharp.Generators.CLI @@ -526,27 +554,27 @@ 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};", property.Field.Name, marshal.Context.Return);
}
}
@ -665,10 +693,10 @@ namespace CppSharp.Generators.CLI @@ -665,10 +693,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 +704,28 @@ namespace CppSharp.Generators.CLI @@ -676,28 +704,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 +777,7 @@ namespace CppSharp.Generators.CLI @@ -749,7 +777,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);

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

@ -607,6 +607,20 @@ namespace CppSharp.Generators.CSharp @@ -607,6 +607,20 @@ namespace CppSharp.Generators.CSharp
return field.Type.Visit(this, field.QualifiedType.Qualifiers);
}
public override bool VisitProperty(Property property)
{
if (!VisitDeclaration(property))
return false;
Context.Parameter = new Parameter
{
Name = Context.ArgName,
QualifiedType = property.QualifiedType
};
return base.VisitProperty(property);
}
public override bool VisitEnumDecl(Enumeration @enum)
{
Context.Return.Write(Context.Parameter.Name);

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

@ -363,8 +363,8 @@ namespace CppSharp.Generators.CSharp @@ -363,8 +363,8 @@ namespace CppSharp.Generators.CSharp
GenerateClassMarshals(@class);
GenerateClassConstructors(@class);
if (@class.IsValueType)
GenerateValueClassFields(@class);
if (@class.IsUnion)
GenerateUnionFields(@class);
GenerateClassMethods(@class);
GenerateClassVariables(@class);
@ -448,26 +448,28 @@ namespace CppSharp.Generators.CSharp @@ -448,26 +448,28 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateValueClassFields(Class @class)
private void GenerateUnionFields(Class @class)
{
GenerateClassFields(@class, field =>
foreach (var field in @class.Fields)
{
var fieldClass = (Class) field.Namespace;
if (!fieldClass.IsValueType)
return;
GenerateClassField(field);
});
}
}
public void GenerateClassInternalsFields(Class @class)
{
if (@class.IsValueType)
{
foreach (var @base in @class.Bases.Where(b => b.IsClass && !b.Class.Ignore))
{
GenerateClassInternalsFields(@base.Class);
}
}
GenerateClassFields(@class, GenerateClassInternalsField);
foreach (var prop in @class.Properties)
foreach (var prop in @class.Properties.Where(p => !p.Ignore && p.Field != null))
{
if (prop.Ignore || prop.Field == null)
continue;
GenerateClassInternalsField(prop.Field);
}
}
@ -604,39 +606,39 @@ namespace CppSharp.Generators.CSharp @@ -604,39 +606,39 @@ namespace CppSharp.Generators.CSharp
WriteLine("struct Internal");
}
private void GenerateStructMarshalingFields(Class @class)
private void GenerateStructMarshalingProperties(Class @class)
{
foreach (var @base in @class.Bases)
{
if (!@base.IsClass || @base.Class.Ignore)
continue;
GenerateStructMarshalingFields(@base.Class);
GenerateStructMarshalingProperties(@base.Class);
}
for (int i = 0; i < @class.Fields.Count; i++)
for (int i = 0; i < @class.Properties.Count; i++)
{
var field = @class.Fields[i];
if (ASTUtils.CheckIgnoreField(field)) continue;
var property = @class.Properties[i];
if (property.Ignore || property.Field == null) continue;
var nativeField = string.Format("{0}->{1}",
Generator.GeneratedIdentifier("ptr"), field.OriginalName);
Generator.GeneratedIdentifier("ptr"), property.Field.OriginalName);
var ctx = new CSharpMarshalContext(Driver)
{
Kind = CSharpMarshalKind.NativeField,
ArgName = field.Name,
ArgName = property.Name,
ReturnVarName = nativeField,
ReturnType = field.QualifiedType
ReturnType = property.QualifiedType
};
var marshal = new CSharpMarshalNativeToManagedPrinter(ctx) { VarSuffix = i };
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};", property.Name, marshal.Context.Return);
}
}
@ -645,12 +647,12 @@ namespace CppSharp.Generators.CSharp @@ -645,12 +647,12 @@ namespace CppSharp.Generators.CSharp
var marshalVar = Generator.GeneratedIdentifier("native");
WriteLine("var {0} = new {1}.Internal();", marshalVar, QualifiedIdentifier(@class));
GenerateStructInternalMarshalingFields(@class, marshalVar);
GenerateStructInternalMarshalingProperties(@class, marshalVar);
WriteLine("return {0};", marshalVar);
}
private void GenerateStructInternalMarshalingFields(Class @class, string marshalVar)
private void GenerateStructInternalMarshalingProperties(Class @class, string marshalVar)
{
foreach (var @base in @class.Bases)
{
@ -658,44 +660,44 @@ namespace CppSharp.Generators.CSharp @@ -658,44 +660,44 @@ namespace CppSharp.Generators.CSharp
continue;
var baseClass = @base.Class;
GenerateStructInternalMarshalingFields(baseClass, marshalVar);
GenerateStructInternalMarshalingProperties(baseClass, marshalVar);
}
foreach (var field in @class.Fields)
foreach (var property in @class.Properties)
{
if (field.Ignore)
if (property.Ignore || property.Field == null)
continue;
GenerateStructInternalMarshalingField(field, marshalVar);
GenerateStructInternalMarshalingProperty(property, marshalVar);
}
}
private void GenerateStructInternalMarshalingField(Field field, string marshalVar)
private void GenerateStructInternalMarshalingProperty(Property property, string marshalVar)
{
var marshalCtx = new CSharpMarshalContext(Driver)
{
ArgName = field.Name,
ArgName = property.Name,
};
var marshal = new CSharpMarshalManagedToNativePrinter(marshalCtx);
field.Visit(marshal);
property.Visit(marshal);
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();
if (isRef)
{
WriteLine("if ({0} != null)", field.Name);
WriteLine("if ({0} != null)", property.Name);
WriteStartBraceIndent();
}
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
WriteLine(marshal.Context.SupportBefore);
WriteLine("{0}.{1} = {2};", marshalVar, field.OriginalName, marshal.Context.Return);
WriteLine("{0}.{1} = {2};", marshalVar, property.OriginalName, marshal.Context.Return);
if (isRef)
WriteCloseBraceIndent();
@ -795,7 +797,7 @@ namespace CppSharp.Generators.CSharp @@ -795,7 +797,7 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateClassField(Field field)
private void GenerateClassField(Field field, bool @public = false)
{
PushBlock(CSharpBlockKind.Field);
@ -805,7 +807,8 @@ namespace CppSharp.Generators.CSharp @@ -805,7 +807,8 @@ namespace CppSharp.Generators.CSharp
if (@class.IsUnion)
WriteLine("[FieldOffset({0})]", field.Offset);
WriteLine("public {0} {1};", field.Type, SafeIdentifier(field.Name));
WriteLine("{0} {1} {2};", @public ? "public" : "private",
field.Type, SafeIdentifier(field.Name));
PopBlock(NewLineKind.BeforeNextBlock);
}
@ -857,7 +860,7 @@ namespace CppSharp.Generators.CSharp @@ -857,7 +860,7 @@ namespace CppSharp.Generators.CSharp
var function = decl as Function;
if (function.IsPure && Driver.Options.GenerateAbstractImpls)
{
Write("; ");
Write(";");
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
@ -895,8 +898,23 @@ namespace CppSharp.Generators.CSharp @@ -895,8 +898,23 @@ namespace CppSharp.Generators.CSharp
}
WriteCloseBraceIndent();
}
else if (decl is Field)
else
{
if (@class.IsValueType)
{
if (@class.IsUnion)
{
WriteStartBraceIndent();
WriteLine("{0} = value;", decl.Name);
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
WriteLine(";");
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
WriteStartBraceIndent();
var field = decl as Field;
@ -950,7 +968,7 @@ namespace CppSharp.Generators.CSharp @@ -950,7 +968,7 @@ namespace CppSharp.Generators.CSharp
var function = decl as Function;
if (function.IsPure && Driver.Options.GenerateAbstractImpls)
{
Write("; ");
Write(";");
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
@ -975,6 +993,22 @@ namespace CppSharp.Generators.CSharp @@ -975,6 +993,22 @@ namespace CppSharp.Generators.CSharp
}
else if (decl is Field)
{
if (@class.IsValueType)
{
if (@class.IsUnion)
{
NewLine();
WriteStartBraceIndent();
WriteLine("return {0};", decl.Name);
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
WriteLine(";");
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
NewLine();
WriteStartBraceIndent();
var field = decl as Field;
@ -1078,9 +1112,28 @@ namespace CppSharp.Generators.CSharp @@ -1078,9 +1112,28 @@ namespace CppSharp.Generators.CSharp
}
private void GenerateClassProperties(Class @class)
{
if (@class.IsValueType)
{
foreach (var @base in @class.Bases.Where(b => b.IsClass && !b.Class.Ignore))
{
GenerateClassProperties(@base.Class);
}
}
GenerateProperties(@class);
}
private void GenerateProperties(Class @class)
{
foreach (var prop in @class.Properties.Where(p => !p.Ignore))
{
if (prop.IsBackedByValueClassField())
{
GenerateClassField(prop.Field, true);
continue;
}
PushBlock(CSharpBlockKind.Property);
// If this is an indexer that returns an address use the real type
@ -1703,7 +1756,7 @@ namespace CppSharp.Generators.CSharp @@ -1703,7 +1756,7 @@ namespace CppSharp.Generators.CSharp
{
WriteLine("var {0} = (Internal*){1}.ToPointer();",
Generator.GeneratedIdentifier("ptr"), "native");
GenerateStructMarshalingFields(@class);
GenerateStructMarshalingProperties(@class);
}
WriteCloseBraceIndent();
@ -1722,7 +1775,7 @@ namespace CppSharp.Generators.CSharp @@ -1722,7 +1775,7 @@ namespace CppSharp.Generators.CSharp
WriteLine("internal void FromInternal(Internal* native)");
WriteStartBraceIndent();
WriteLine("var {0} = {1};", Generator.GeneratedIdentifier("ptr"), "native");
GenerateStructMarshalingFields(@class);
GenerateStructMarshalingProperties(@class);
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}

11
src/Generator/Passes/FieldToPropertyPass.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators;
namespace CppSharp.Passes
{
@ -14,9 +15,6 @@ namespace CppSharp.Passes @@ -14,9 +15,6 @@ namespace CppSharp.Passes
if (@class == null)
return false;
if (@class.IsValueType)
return false;
if (ASTUtils.CheckIgnoreField(field))
return false;
@ -42,6 +40,13 @@ namespace CppSharp.Passes @@ -42,6 +40,13 @@ namespace CppSharp.Passes
Field = field
};
// do not rename value-class fields because they would be
// generated as fields later on even though they are wrapped by properties;
// that is, in turn, because it's cleaner to write
// the struct marshalling logic just for properties
if (!prop.IsBackedByValueClassField())
field.Name = Generator.GeneratedIdentifier(field.Name);
@class.Properties.Add(prop);
Log.Debug("Property created from field: {0}::{1}", @class.Name,

1
src/Generator/Passes/verbs.txt

@ -5797,6 +5797,7 @@ prepartaken @@ -5797,6 +5797,7 @@ prepartaken
prepartook
prepave
prepay
prepend
prepenetrate
prepersuade
preperuse

16
tests/Basic/Basic.Tests.cs

@ -164,5 +164,21 @@ public class BasicTests : GeneratorTestFixture @@ -164,5 +164,21 @@ public class BasicTests : GeneratorTestFixture
var doubleSum = delegates.A(2) + delegates.B(2);
Assert.AreEqual(8, doubleSum);
}
[Test]
public void TestUnion()
{
Hello.NestedPublic nestedPublic = new Hello.NestedPublic();
nestedPublic.j = 5;
Assert.That(nestedPublic.l, Is.EqualTo(5));
Assert.That(nestedPublic.g, Is.Not.EqualTo(0));
}
public void TestPropertyChains()
{
var bar2 = new Bar2();
bar2.pointerToStruct.A = 15;
Assert.That(bar2.pointerToStruct.A, Is.EqualTo(15));
}
}

1
tests/Basic/Basic.h

@ -90,6 +90,7 @@ public: @@ -90,6 +90,7 @@ public:
union NestedPublic {
int j;
float g;
long l;
};
Hello ();

Loading…
Cancel
Save