Browse Source

Fixed handling of property indexers in the CLI generator.

pull/219/merge
triton 11 years ago
parent
commit
e95a2929a8
  1. 3
      src/Generator.Tests/GeneratorTest.cs
  2. 38
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  3. 41
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  4. 22
      src/Generator/Passes/CheckOperatorsOverloads.cs
  5. 7
      tests/Basic/Basic.Tests.cs
  6. 27
      tests/Basic/Basic.h

3
src/Generator.Tests/GeneratorTest.cs

@ -30,8 +30,9 @@ namespace CppSharp.Utils
options.OutputDir = Path.Combine(GetOutputDirectory(), "gen", name); options.OutputDir = Path.Combine(GetOutputDirectory(), "gen", name);
options.SharedLibraryName = name + ".Native"; options.SharedLibraryName = name + ".Native";
options.GenerateLibraryNamespace = true; options.GenerateLibraryNamespace = true;
options.Quiet = true; options.Quiet = false;
options.IgnoreParseWarnings = true; options.IgnoreParseWarnings = true;
options.Verbose = true;
driver.Diagnostics.EmitMessage(""); driver.Diagnostics.EmitMessage("");
driver.Diagnostics.EmitMessage("Generating bindings for {0} ({1})", driver.Diagnostics.EmitMessage("Generating bindings for {0} ({1})",

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

@ -621,6 +621,22 @@ namespace CppSharp.Generators.CLI
PopIndent(); 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) public void GenerateProperty(Property property)
{ {
if (!(property.HasGetter || property.HasSetter)) if (!(property.HasGetter || property.HasSetter))
@ -629,16 +645,24 @@ namespace CppSharp.Generators.CLI
PushBlock(CLIBlockKind.Property, property); PushBlock(CLIBlockKind.Property, property);
var type = property.QualifiedType.Visit(TypePrinter); var type = property.QualifiedType.Visit(TypePrinter);
WriteLine("property {0} {1}", type, property.Name); if (property.IsIndexer)
WriteStartBraceIndent(); {
GenerateIndexer(property);
}
else
{
WriteLine("property {0} {1}", type, property.Name);
WriteStartBraceIndent();
if(property.HasGetter) if (property.HasGetter)
WriteLine("{0} get();", type); WriteLine("{0} get();", type);
if(property.HasSetter) if (property.HasSetter)
WriteLine("void set({0});", type); WriteLine("void set({0});", type);
WriteCloseBraceIndent();
}
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }

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

@ -312,7 +312,6 @@ namespace CppSharp.Generators.CLI
if (property.Ignore) return; if (property.Ignore) return;
PushBlock(CLIBlockKind.Property); PushBlock(CLIBlockKind.Property);
var @class = property.Namespace as Class;
if (property.Field != null) if (property.Field != null)
{ {
@ -343,15 +342,23 @@ namespace CppSharp.Generators.CLI
if (decl == null) if (decl == null)
return; return;
WriteLine("void {0}::{1}::set({2} value)", QualifiedIdentifier(@class), var method = decl as Method;
name, type); var isIndexer = method != null &&
method.OperatorKind == CXXOperatorKind.Subscript;
var args = new List<string>();
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(); WriteStartBraceIndent();
if (decl is Function) if (decl is Function && !isIndexer)
{ {
var func = decl as Function; var func = decl as Function;
if(func.Parameters[0].Name != "value")
WriteLine("auto {0} = value;", func.Parameters[0].Name);
GenerateFunctionCall(func, @class); GenerateFunctionCall(func, @class);
} }
else else
@ -386,6 +393,9 @@ namespace CppSharp.Generators.CLI
variable = string.Format("((::{0}*)NativePtr)->{1}", variable = string.Format("((::{0}*)NativePtr)->{1}",
@class.QualifiedOriginalName, decl.OriginalName); @class.QualifiedOriginalName, decl.OriginalName);
if (isIndexer)
variable += "(index)";
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore); Write(marshal.Context.SupportBefore);
@ -402,8 +412,17 @@ namespace CppSharp.Generators.CLI
if (decl == null) if (decl == null)
return; return;
WriteLine("{0} {1}::{2}::get()", type, QualifiedIdentifier(@class), var method = decl as Method;
name); var isIndexer = method != null &&
method.OperatorKind == CXXOperatorKind.Subscript;
var args = new List<string>();
if (isIndexer)
args.Add("int index");
WriteLine("{0} {1}::{2}::get({3})", type, QualifiedIdentifier(@class),
name, string.Join(", ", args));
WriteStartBraceIndent(); WriteStartBraceIndent();
if (decl is Function) if (decl is Function)
@ -855,7 +874,8 @@ namespace CppSharp.Generators.CLI
var typeName = method.ConversionType.Visit(typePrinter); var typeName = method.ConversionType.Visit(typePrinter);
WriteLine("({0}) {1};", typeName, @params[0].Name); 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(); var opName = function.Name.Replace("operator", "").Trim();
@ -865,8 +885,7 @@ namespace CppSharp.Generators.CLI
WriteLine("{0} {1};", opName, @params[0].Name); WriteLine("{0} {1};", opName, @params[0].Name);
break; break;
case CXXOperatorArity.Binary: case CXXOperatorArity.Binary:
WriteLine("{0} {1} {2};", @params[0].Name, opName, WriteLine("{0} {1} {2};", @params[0].Name, opName, @params[1].Name);
@params[1].Name);
break; break;
} }
} }

22
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", Name = "Item",
QualifiedType = @operator.ReturnType, QualifiedType = @operator.ReturnType,
Access = @operator.Access, Access = @operator.Access,
Namespace = @class, Namespace = @class,
GetMethod = @operator 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; 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); @class.Properties.Add(property);
@operator.IsGenerated = false; @operator.IsGenerated = false;
} }

7
tests/Basic/Basic.Tests.cs

@ -218,5 +218,12 @@ public class BasicTests : GeneratorTestFixture
Assert.That(foo2.testCharMarshalling(c), Is.EqualTo(c)); Assert.That(foo2.testCharMarshalling(c), Is.EqualTo(c));
Assert.Catch<ArgumentException>(() => foo2.testCharMarshalling('ж')); Assert.Catch<ArgumentException>(() => foo2.testCharMarshalling('ж'));
} }
[Test]
public unsafe void TestIndexers()
{
var someStruct = new SomeStruct();
Assert.That(someStruct[0], Is.EqualTo(1));
}
} }

27
tests/Basic/Basic.h

@ -304,11 +304,12 @@ struct EmptyNamedNestedEnum
}; };
typedef unsigned long foo_t; typedef unsigned long foo_t;
typedef struct SomeStruct typedef DLL_API struct SomeStruct
{ {
const foo_t& operator[](int i) const { return p[i]; } SomeStruct() : p(1) {}
foo_t& operator[](int i) { return p[i]; } const foo_t& operator[](int i) const { return p; }
foo_t* p; foo_t operator[](int i) { return p; }
foo_t p;
} }
SomeStruct; SomeStruct;
@ -324,12 +325,12 @@ namespace SomeNamespace
virtual void AbstractMethod() = 0; virtual void AbstractMethod() = 0;
}; };
} }
// Test operator overloads // Test operator overloads
class ClassWithOverloadedOperators class ClassWithOverloadedOperators
{ {
public: public:
operator char(); operator char();
operator int(); operator int();
operator short(); operator short();
}; };

Loading…
Cancel
Save