Browse Source

Added support for writing using indexers.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/62/head
Dimitar Dobrev 12 years ago
parent
commit
b82aebab3a
  1. 1
      build/Tests.lua
  2. 5
      src/AST/Type.cs
  3. 3
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  4. 37
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  5. 23
      src/Generator/Passes/CheckOperatorsOverloads.cs
  6. 22
      tests/CSharpTemp/CSharpTemp.Tests.cs
  7. 28
      tests/CSharpTemp/CSharpTemp.cpp
  8. 15
      tests/CSharpTemp/CSharpTemp.h

1
build/Tests.lua

@ -90,6 +90,7 @@ function SetupTestProjectsCSharp(name, file, lib)
kind "SharedLib" kind "SharedLib"
language "C#" language "C#"
location "." location "."
flags { "Unsafe" }
files { name .. ".Tests.cs" } files { name .. ".Tests.cs" }
links { name .. ".CSharp" } links { name .. ".CSharp" }

5
src/AST/Type.cs

@ -47,6 +47,11 @@ namespace CppSharp.AST
return tag.Declaration is Enumeration; return tag.Declaration is Enumeration;
} }
public bool IsAddress()
{
return IsPointer() || IsReference();
}
public bool IsPointer() public bool IsPointer()
{ {
var functionPointer = this as MemberPointerType; var functionPointer = this as MemberPointerType;

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

@ -239,6 +239,7 @@ namespace CppSharp.Generators.CSharp
} }
if (@class.IsRefType && if (@class.IsRefType &&
(Context.ReturnType.Qualifiers.IsConst || !Context.ReturnType.Type.IsAddress()) &&
(!Context.Driver.Options.GenerateAbstractImpls || !@class.IsAbstract)) (!Context.Driver.Options.GenerateAbstractImpls || !@class.IsAbstract))
{ {
var instanceName = Generator.GeneratedIdentifier("instance"); var instanceName = Generator.GeneratedIdentifier("instance");
@ -533,7 +534,7 @@ namespace CppSharp.Generators.CSharp
return; return;
} }
if (Context.Parameter.Type.IsPointer() || Context.Parameter.Type.IsReference()) if (Context.Parameter.Type.IsAddress())
{ {
Context.Return.Write("{0}.{1}", Helpers.SafeIdentifier(Context.Parameter.Name), Context.Return.Write("{0}.{1}", Helpers.SafeIdentifier(Context.Parameter.Name),
Helpers.InstanceIdentifier); Helpers.InstanceIdentifier);

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

@ -725,7 +725,7 @@ namespace CppSharp.Generators.CSharp
return Tuple.Create(library, decl.Mangled); return Tuple.Create(library, decl.Mangled);
} }
private void GeneratePropertySetter<T>(T decl, Class @class) private void GeneratePropertySetter<T>(QualifiedType returnType, T decl, Class @class)
where T : Declaration, ITypedDecl where T : Declaration, ITypedDecl
{ {
PushBlock(CSharpBlockKind.Method); PushBlock(CSharpBlockKind.Method);
@ -753,8 +753,16 @@ namespace CppSharp.Generators.CSharp
param.QualifiedType = function.Parameters[0].QualifiedType; param.QualifiedType = function.Parameters[0].QualifiedType;
var parameters = new List<Parameter> { param }; var method = function as Method;
GenerateInternalFunctionCall(function, parameters); if (method != null && method.IsSynthetized)
{
GenerateIndexerSetter(returnType, method);
}
else
{
var parameters = new List<Parameter> { param };
GenerateInternalFunctionCall(function, parameters);
}
} }
else if (decl is Field) else if (decl is Field)
{ {
@ -779,6 +787,23 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
private void GenerateIndexerSetter(QualifiedType returnType, Function function)
{
Type type;
returnType.Type.IsPointerTo(out type);
PrimitiveType primitiveType;
if (type.IsPrimitiveType(out primitiveType))
{
WriteLine("*({0}*) this[{1}] = *({0}*) value;",
type.ToString(), function.Parameters[0].Name);
}
else
{
WriteLine("*({0}.Internal*) this[{1}].{2} = *({0}.Internal*) value.{2};",
type.ToString(), function.Parameters[0].Name, Helpers.InstanceIdentifier);
}
}
private void GeneratePropertyGetter<T>(T decl, Class @class) private void GeneratePropertyGetter<T>(T decl, Class @class)
where T : Declaration, ITypedDecl where T : Declaration, ITypedDecl
{ {
@ -907,7 +932,7 @@ namespace CppSharp.Generators.CSharp
GeneratePropertyGetter(prop.Field, @class); GeneratePropertyGetter(prop.Field, @class);
if (prop.HasSetter) if (prop.HasSetter)
GeneratePropertySetter(prop.Field, @class); GeneratePropertySetter(prop.Field.QualifiedType, prop.Field, @class);
} }
else else
{ {
@ -915,7 +940,7 @@ namespace CppSharp.Generators.CSharp
GeneratePropertyGetter(prop.GetMethod, @class); GeneratePropertyGetter(prop.GetMethod, @class);
if (prop.HasSetter) if (prop.HasSetter)
GeneratePropertySetter(prop.SetMethod, @class); GeneratePropertySetter(prop.GetMethod.ReturnType, prop.SetMethod, @class);
} }
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -938,7 +963,7 @@ namespace CppSharp.Generators.CSharp
GeneratePropertyGetter(variable, @class); GeneratePropertyGetter(variable, @class);
if (!variable.QualifiedType.Qualifiers.IsConst) if (!variable.QualifiedType.Qualifiers.IsConst)
GeneratePropertySetter(variable, @class); GeneratePropertySetter(variable.QualifiedType, variable, @class);
WriteCloseBraceIndent(); WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);

23
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -86,14 +86,23 @@ namespace CppSharp.Passes
private static void CreateIndexer(Class @class, Method @operator) private static void CreateIndexer(Class @class, Method @operator)
{ {
Property property = new Property Property 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); property.Parameters.AddRange(@operator.Parameters);
if (!@operator.ReturnType.Qualifiers.IsConst && @operator.ReturnType.Type.IsAddress())
{
property.SetMethod = new Method(@operator)
{
ReturnType = new QualifiedType(
new BuiltinType(PrimitiveType.Void)),
IsSynthetized = true
};
}
@class.Properties.Add(property); @class.Properties.Add(property);
@operator.IsGenerated = false; @operator.IsGenerated = false;
} }

22
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -1,4 +1,6 @@
using System.Reflection; using System;
using System.Reflection;
using CSharpTemp;
using NUnit.Framework; using NUnit.Framework;
using Foo = CSharpTemp.Foo; using Foo = CSharpTemp.Foo;
@ -6,10 +8,24 @@ using Foo = CSharpTemp.Foo;
public class CSharpTempTests public class CSharpTempTests
{ {
[Test] [Test]
public void TestIndexer() public unsafe void TestIndexer()
{ {
var foo = new Foo(); var foo = new Foo();
Assert.That(foo[0], Is.EqualTo(5));
// TODO: Most of the ugliness below will disappear when pointers to simple types are represented by C#-pointers or ref modifiers instead of the nasty IntPtr
var value = *(int*) foo[0];
Assert.That(value, Is.EqualTo(50));
int x = 250;
foo[0] = new IntPtr(&x);
value = *(int*) foo[0];
Assert.That(value, Is.EqualTo(x));
Assert.That(foo[(uint) 0], Is.EqualTo(15));
var bar = new Bar();
Assert.That(bar[0].A, Is.EqualTo(10));
bar[0] = new Foo { A = 25 };
Assert.That(bar[0].A, Is.EqualTo(25));
} }
[Test] [Test]

28
tests/CSharpTemp/CSharpTemp.cpp

@ -1,12 +1,32 @@
#include "CSharpTemp.h" #include "CSharpTemp.h"
// TODO: move this, it has nothing to do with Unicode, it's here only not to break the CLI branch Foo::Foo()
{
A = 10;
P = 50;
}
int Foo::operator[](int i) const int Foo::operator[](int i) const
{ {
return 5; return 5;
} }
int Foo::operator[](int i) int Foo::operator[](unsigned int i)
{ {
return 5; return 15;
} }
int& Foo::operator[](int i)
{
return P;
}
const Foo& Bar::operator[](int i) const
{
return m_foo;
}
Foo& Bar::operator[](int i)
{
return m_foo;
}

15
tests/CSharpTemp/CSharpTemp.h

@ -7,9 +7,22 @@
class DLL_API Foo class DLL_API Foo
{ {
public: public:
Foo();
int operator[](int i) const; int operator[](int i) const;
int operator[](int i); int operator[](unsigned int i);
int& operator[](int i);
int A;
protected: protected:
int P; int P;
}; };
class DLL_API Bar
{
public:
const Foo& operator[](int i) const;
Foo& operator[](int i);
private:
Foo m_foo;
};

Loading…
Cancel
Save