From e95a2929a8bbd461a9691d9c64589daa35922498 Mon Sep 17 00:00:00 2001 From: triton Date: Sat, 12 Apr 2014 14:25:42 +0100 Subject: [PATCH] Fixed handling of property indexers in the CLI generator. --- src/Generator.Tests/GeneratorTest.cs | 3 +- .../Generators/CLI/CLIHeadersTemplate.cs | 38 +++++++++++++---- .../Generators/CLI/CLISourcesTemplate.cs | 41 ++++++++++++++----- .../Passes/CheckOperatorsOverloads.cs | 22 +++++++--- tests/Basic/Basic.Tests.cs | 7 ++++ tests/Basic/Basic.h | 27 ++++++------ 6 files changed, 101 insertions(+), 37 deletions(-) diff --git a/src/Generator.Tests/GeneratorTest.cs b/src/Generator.Tests/GeneratorTest.cs index dcc4d50b..cde7ff14 100644 --- a/src/Generator.Tests/GeneratorTest.cs +++ b/src/Generator.Tests/GeneratorTest.cs @@ -30,8 +30,9 @@ namespace CppSharp.Utils options.OutputDir = Path.Combine(GetOutputDirectory(), "gen", name); options.SharedLibraryName = name + ".Native"; options.GenerateLibraryNamespace = true; - options.Quiet = true; + options.Quiet = false; options.IgnoreParseWarnings = true; + options.Verbose = true; driver.Diagnostics.EmitMessage(""); driver.Diagnostics.EmitMessage("Generating bindings for {0} ({1})", diff --git a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs index 041cc651..8403e3f3 100644 --- a/src/Generator/Generators/CLI/CLIHeadersTemplate.cs +++ b/src/Generator/Generators/CLI/CLIHeadersTemplate.cs @@ -621,6 +621,22 @@ namespace CppSharp.Generators.CLI PopIndent(); } + public void GenerateIndexer(Property property) + { + var type = property.QualifiedType.Visit(TypePrinter); + + WriteLine("property {0} default[int]", type); + WriteStartBraceIndent(); + + if (property.HasGetter) + WriteLine("{0} get(int index);", type); + + if (property.HasSetter) + WriteLine("void set(int index, {0});", type); + + WriteCloseBraceIndent(); + } + public void GenerateProperty(Property property) { if (!(property.HasGetter || property.HasSetter)) @@ -629,16 +645,24 @@ namespace CppSharp.Generators.CLI PushBlock(CLIBlockKind.Property, property); var type = property.QualifiedType.Visit(TypePrinter); - WriteLine("property {0} {1}", type, property.Name); - WriteStartBraceIndent(); + if (property.IsIndexer) + { + GenerateIndexer(property); + } + else + { + WriteLine("property {0} {1}", type, property.Name); + WriteStartBraceIndent(); - if(property.HasGetter) - WriteLine("{0} get();", type); + if (property.HasGetter) + WriteLine("{0} get();", type); - if(property.HasSetter) - WriteLine("void set({0});", type); + if (property.HasSetter) + WriteLine("void set({0});", type); + + WriteCloseBraceIndent(); + } - WriteCloseBraceIndent(); PopBlock(NewLineKind.BeforeNextBlock); } diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index abde1896..5dae9055 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -312,7 +312,6 @@ namespace CppSharp.Generators.CLI if (property.Ignore) return; PushBlock(CLIBlockKind.Property); - var @class = property.Namespace as Class; if (property.Field != null) { @@ -343,15 +342,23 @@ namespace CppSharp.Generators.CLI if (decl == null) return; - WriteLine("void {0}::{1}::set({2} value)", QualifiedIdentifier(@class), - name, type); + var method = decl as Method; + var isIndexer = method != null && + method.OperatorKind == CXXOperatorKind.Subscript; + + var args = new List(); + if (isIndexer) + args.Add("int index"); + args.Add(string.Format("{0} value", type)); + + WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class), + name, string.Join(", ", args)); + WriteStartBraceIndent(); - if (decl is Function) + if (decl is Function && !isIndexer) { var func = decl as Function; - if(func.Parameters[0].Name != "value") - WriteLine("auto {0} = value;", func.Parameters[0].Name); GenerateFunctionCall(func, @class); } else @@ -386,6 +393,9 @@ namespace CppSharp.Generators.CLI variable = string.Format("((::{0}*)NativePtr)->{1}", @class.QualifiedOriginalName, decl.OriginalName); + if (isIndexer) + variable += "(index)"; + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) Write(marshal.Context.SupportBefore); @@ -402,8 +412,17 @@ namespace CppSharp.Generators.CLI if (decl == null) return; - WriteLine("{0} {1}::{2}::get()", type, QualifiedIdentifier(@class), - name); + var method = decl as Method; + var isIndexer = method != null && + method.OperatorKind == CXXOperatorKind.Subscript; + + var args = new List(); + if (isIndexer) + args.Add("int index"); + + WriteLine("{0} {1}::{2}::get({3})", type, QualifiedIdentifier(@class), + name, string.Join(", ", args)); + WriteStartBraceIndent(); if (decl is Function) @@ -855,7 +874,8 @@ namespace CppSharp.Generators.CLI var typeName = method.ConversionType.Visit(typePrinter); WriteLine("({0}) {1};", typeName, @params[0].Name); } - else if (function.IsOperator) + else if (function.IsOperator && + function.OperatorKind != CXXOperatorKind.Subscript) { var opName = function.Name.Replace("operator", "").Trim(); @@ -865,8 +885,7 @@ namespace CppSharp.Generators.CLI WriteLine("{0} {1};", opName, @params[0].Name); break; case CXXOperatorArity.Binary: - WriteLine("{0} {1} {2};", @params[0].Name, opName, - @params[1].Name); + WriteLine("{0} {1} {2};", @params[0].Name, opName, @params[1].Name); break; } } diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index 565cf571..841bcd5b 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -86,19 +86,31 @@ namespace CppSharp.Passes } } - private static void CreateIndexer(Class @class, Method @operator) + void CreateIndexer(Class @class, Method @operator) { - Property property = new Property + var property = new Property { Name = "Item", QualifiedType = @operator.ReturnType, Access = @operator.Access, Namespace = @class, GetMethod = @operator - }; - property.Parameters.AddRange(@operator.Parameters); - if (!@operator.ReturnType.Qualifiers.IsConst && @operator.ReturnType.Type.IsAddress()) + }; + + if (!@operator.ReturnType.Qualifiers.IsConst && @operator.ReturnType.Type.IsAddress()) property.SetMethod = @operator; + + // C++/CLI uses "default" as the indexer property name. + if (Driver.Options.IsCLIGenerator) + property.Name = "default"; + + property.GetMethod.Parameters[0].Name = "index"; + + if (property.SetMethod != null) + property.SetMethod.Parameters[0].Name = "index"; + + property.Parameters.AddRange(@operator.Parameters); + @class.Properties.Add(property); @operator.IsGenerated = false; } diff --git a/tests/Basic/Basic.Tests.cs b/tests/Basic/Basic.Tests.cs index ba79944c..e5674ce2 100644 --- a/tests/Basic/Basic.Tests.cs +++ b/tests/Basic/Basic.Tests.cs @@ -218,5 +218,12 @@ public class BasicTests : GeneratorTestFixture Assert.That(foo2.testCharMarshalling(c), Is.EqualTo(c)); Assert.Catch(() => foo2.testCharMarshalling('ж')); } + + [Test] + public unsafe void TestIndexers() + { + var someStruct = new SomeStruct(); + Assert.That(someStruct[0], Is.EqualTo(1)); + } } \ No newline at end of file diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 6554f53c..83f93fc7 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -304,11 +304,12 @@ struct EmptyNamedNestedEnum }; typedef unsigned long foo_t; -typedef struct SomeStruct +typedef DLL_API struct SomeStruct { - const foo_t& operator[](int i) const { return p[i]; } - foo_t& operator[](int i) { return p[i]; } - foo_t* p; + SomeStruct() : p(1) {} + const foo_t& operator[](int i) const { return p; } + foo_t operator[](int i) { return p; } + foo_t p; } SomeStruct; @@ -324,12 +325,12 @@ namespace SomeNamespace virtual void AbstractMethod() = 0; }; } - -// Test operator overloads -class ClassWithOverloadedOperators -{ -public: - operator char(); - operator int(); - operator short(); -}; \ No newline at end of file + +// Test operator overloads +class ClassWithOverloadedOperators +{ +public: + operator char(); + operator int(); + operator short(); +};