Browse Source

Merge pull request #81 from ddobrev/master

Consider indirect args and value type - pointer type pairs when generating properties
pull/103/head
João Matos 12 years ago
parent
commit
20c06646f4
  1. 33
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  2. 13
      src/Generator/Passes/CheckOperatorsOverloads.cs
  3. 30
      src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs
  4. 2
      src/Generator/Passes/MultipleInheritancePass.cs
  5. 15
      src/Generator/Passes/ParamTypeToInterfacePass.cs
  6. 2
      src/Generator/Passes/verbs.txt
  7. 9
      tests/CSharpTemp/CSharpTemp.Tests.cs
  8. 39
      tests/CSharpTemp/CSharpTemp.cpp
  9. 1
      tests/CSharpTemp/CSharpTemp.cs
  10. 17
      tests/CSharpTemp/CSharpTemp.h

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

@ -536,7 +536,7 @@ namespace CppSharp.Generators.CSharp @@ -536,7 +536,7 @@ namespace CppSharp.Generators.CSharp
TypePrinter.PushContext(CSharpTypePrinterContextKind.Native);
var retParam = new Parameter { QualifiedType = function.ReturnType };
var retParam = new Parameter { QualifiedType = function.OriginalReturnType };
retType = retParam.CSharpType(TypePrinter);
var method = function as Method;
@ -1245,11 +1245,21 @@ namespace CppSharp.Generators.CSharp @@ -1245,11 +1245,21 @@ namespace CppSharp.Generators.CSharp
NewLine();
}
private void GenerateVTableClassSetupCall(Class @class)
private void GenerateVTableClassSetupCall(Class @class, bool addPointerGuard = false)
{
var entries = GetVTableMethodEntries(@class);
if (Options.GenerateVirtualTables && @class.IsDynamic && entries.Count != 0)
{
// called from internal ctors which may have been passed an IntPtr.Zero
if (addPointerGuard)
{
WriteLine("if ({0} != global::System.IntPtr.Zero)", Helpers.InstanceIdentifier);
PushIndent();
}
WriteLine("SetupVTables({0});", Generator.GeneratedIdentifier("Instance"));
if (addPointerGuard)
PopIndent();
}
}
private void GenerateVTableManagedCall(Method method)
@ -1285,8 +1295,7 @@ namespace CppSharp.Generators.CSharp @@ -1285,8 +1295,7 @@ namespace CppSharp.Generators.CSharp
marshals.Add(marshal.Context.Return);
}
var hasReturn = !method.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void)
&& !method.HasIndirectReturnTypeParameter;
var hasReturn = !method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void);
if (hasReturn)
Write("var _ret = ");
@ -1300,8 +1309,6 @@ namespace CppSharp.Generators.CSharp @@ -1300,8 +1309,6 @@ namespace CppSharp.Generators.CSharp
InvokeProperty(method, marshals);
}
// TODO: Handle hidden structure return types.
if (hasReturn)
{
var param = new Parameter
@ -1319,7 +1326,7 @@ namespace CppSharp.Generators.CSharp @@ -1319,7 +1326,7 @@ namespace CppSharp.Generators.CSharp
};
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
method.ReturnType.Visit(marshal);
method.OriginalReturnType.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
@ -1350,7 +1357,7 @@ namespace CppSharp.Generators.CSharp @@ -1350,7 +1357,7 @@ namespace CppSharp.Generators.CSharp
PushBlock(CSharpBlockKind.VTableDelegate);
WriteLine("[SuppressUnmanagedCodeSecurity]");
WriteLine("[UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.{0})]",
WriteLine("[UnmanagedFunctionPointerAttribute(global::System.Runtime.InteropServices.CallingConvention.{0})]",
Helpers.ToCSharpCallConv(method.CallingConvention));
CSharpTypePrinterResult retType;
@ -1423,7 +1430,7 @@ namespace CppSharp.Generators.CSharp @@ -1423,7 +1430,7 @@ namespace CppSharp.Generators.CSharp
delegateName = delegateInstance + "Delegate";
delegateRaise = delegateInstance + "RaiseInstance";
WriteLine("[UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.Cdecl)]");
WriteLine("[UnmanagedFunctionPointerAttribute(global::System.Runtime.InteropServices.CallingConvention.Cdecl)]");
WriteLine("delegate void {0}({1});", delegateName, args);
WriteLine("{0} {1};", delegateName, delegateRaise);
NewLine();
@ -1616,7 +1623,7 @@ namespace CppSharp.Generators.CSharp @@ -1616,7 +1623,7 @@ namespace CppSharp.Generators.CSharp
if (ShouldGenerateClassNativeField(@class))
{
WriteLine("{0} = native;", Helpers.InstanceIdentifier);
GenerateVTableClassSetupCall(@class);
GenerateVTableClassSetupCall(@class, true);
}
}
else
@ -1695,7 +1702,7 @@ namespace CppSharp.Generators.CSharp @@ -1695,7 +1702,7 @@ namespace CppSharp.Generators.CSharp
public void GenerateMethod(Method method, Class @class)
{
PushBlock(CSharpBlockKind.Method);
PushBlock(CSharpBlockKind.Method, method);
GenerateDeclarationCommon(method);
if (method.ExplicitInterfaceImpl == null)
@ -2188,7 +2195,7 @@ namespace CppSharp.Generators.CSharp @@ -2188,7 +2195,7 @@ namespace CppSharp.Generators.CSharp
else if (typedef.Type.IsPointerTo(out functionType))
{
PushBlock(CSharpBlockKind.Typedef);
WriteLine("[UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.{0})]",
WriteLine("[UnmanagedFunctionPointerAttribute(global::System.Runtime.InteropServices.CallingConvention.{0})]",
Helpers.ToCSharpCallConv(functionType.CallingConvention));
TypePrinter.PushContext(CSharpTypePrinterContextKind.Native);
WriteLine("{0}unsafe {1};",
@ -2317,7 +2324,7 @@ namespace CppSharp.Generators.CSharp @@ -2317,7 +2324,7 @@ namespace CppSharp.Generators.CSharp
Write("[DllImport(\"{0}\", ", libName);
var callConv = Helpers.ToCSharpCallConv(function.CallingConvention);
WriteLine("CallingConvention = System.Runtime.InteropServices.CallingConvention.{0},",
WriteLine("CallingConvention = global::System.Runtime.InteropServices.CallingConvention.{0},",
callConv);
WriteLineIndent("EntryPoint=\"{0}\")]", function.Mangled);

13
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -169,11 +169,8 @@ namespace CppSharp.Passes @@ -169,11 +169,8 @@ namespace CppSharp.Passes
case CXXOperatorKind.Minus:
case CXXOperatorKind.Exclaim:
case CXXOperatorKind.Tilde:
case CXXOperatorKind.PlusPlus:
case CXXOperatorKind.MinusMinus:
// These binary operators can be overloaded
case CXXOperatorKind.Star:
case CXXOperatorKind.Slash:
case CXXOperatorKind.Percent:
case CXXOperatorKind.Amp:
@ -193,12 +190,22 @@ namespace CppSharp.Passes @@ -193,12 +190,22 @@ namespace CppSharp.Passes
case CXXOperatorKind.Conversion:
return true;
// Only prefix operators can be overloaded
case CXXOperatorKind.PlusPlus:
case CXXOperatorKind.MinusMinus:
return @operator.Parameters.Count == 0;
// Bitwise shift operators can only be overloaded if the second parameter is int
case CXXOperatorKind.LessLess:
case CXXOperatorKind.GreaterGreater:
PrimitiveType primitiveType;
return @operator.Parameters.Last().Type.IsPrimitiveType(out primitiveType) &&
primitiveType == PrimitiveType.Int32;
// No parameters means the dereference operator - cannot be overloaded
case CXXOperatorKind.Star:
return @operator.Parameters.Count > 0;
// Assignment operators cannot be overloaded
case CXXOperatorKind.PlusEqual:
case CXXOperatorKind.MinusEqual:

30
src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs

@ -6,6 +6,7 @@ using System.Linq; @@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using CppSharp.AST;
using Type = CppSharp.AST.Type;
namespace CppSharp.Passes
{
@ -94,7 +95,8 @@ namespace CppSharp.Passes @@ -94,7 +95,8 @@ namespace CppSharp.Passes
{
string name = GetPropertyName(getter.Name);
if (string.Compare(name, afterSet, StringComparison.OrdinalIgnoreCase) == 0 &&
getter.ReturnType == setter.Parameters[0].QualifiedType &&
GetUnderlyingType(getter.OriginalReturnType).Equals(
GetUnderlyingType(setter.Parameters[0].QualifiedType)) &&
!type.Methods.Any(
m =>
m != getter &&
@ -132,6 +134,18 @@ namespace CppSharp.Passes @@ -132,6 +134,18 @@ namespace CppSharp.Passes
}
}
private static Type GetUnderlyingType(QualifiedType type)
{
TagType tagType = type.Type as TagType;
if (tagType != null)
return type.Type;
// TODO: we should normally check pointer types for const;
// however, there's some bug, probably in the parser, that returns IsConst = false for "const Type& arg"
// so skip the check for the time being
PointerType pointerType = type.Type as PointerType;
return pointerType != null ? pointerType.Pointee : type.Type;
}
private static void GenerateProperty(DeclarationContext context, Method getter, Method setter = null)
{
Class type = (Class) context;
@ -142,13 +156,14 @@ namespace CppSharp.Passes @@ -142,13 +156,14 @@ namespace CppSharp.Passes
Property property = new Property();
property.Name = GetPropertyName(getter.Name);
property.Namespace = type;
property.QualifiedType = getter.ReturnType;
property.QualifiedType = getter.OriginalReturnType;
if (getter.IsOverride || (setter != null && setter.IsOverride))
{
Property baseVirtualProperty = type.GetRootBaseProperty(property);
if (baseVirtualProperty.SetMethod == null)
setter = null;
foreach (Method method in type.Methods.Where(m => m.Name == property.Name && m.Parameters.Count > 0))
foreach (Method method in type.Methods.Where(m => m.Name == property.Name &&
m.Parameters.Any(p => p.Kind != ParameterKind.IndirectReturnType)))
method.Name = "get" + method.Name;
}
property.GetMethod = getter;
@ -204,7 +219,7 @@ namespace CppSharp.Passes @@ -204,7 +219,7 @@ namespace CppSharp.Passes
private void DistributeMethod(Method method)
{
if (GetFirstWord(method.Name) == "set" && method.Name.Length > 3 &&
method.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void))
method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void))
{
if (method.Parameters.Count == 1)
setters.Add(method);
@ -215,15 +230,16 @@ namespace CppSharp.Passes @@ -215,15 +230,16 @@ namespace CppSharp.Passes
{
if (IsGetter(method))
getters.Add(method);
if (method.Parameters.Count == 0)
if (method.Parameters.All(p => p.Kind == ParameterKind.IndirectReturnType))
nonSetters.Add(method);
}
}
private bool IsGetter(Method method)
{
if (method.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void) ||
method.Parameters.Count > 0 || method.IsDestructor)
if (method.IsDestructor ||
(method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void)) ||
method.Parameters.Any(p => p.Kind != ParameterKind.IndirectReturnType))
return false;
var result = GetFirstWord(method.Name);
return (result.Length < method.Name.Length &&

2
src/Generator/Passes/MultipleInheritancePass.cs

@ -68,7 +68,7 @@ namespace CppSharp.Passes @@ -68,7 +68,7 @@ namespace CppSharp.Passes
@interface.Methods.AddRange(
from m in @base.Methods
where !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore
where !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore && !m.IsOperator
select new Method(m) { Namespace = @interface });
@interface.Properties.AddRange(

15
src/Generator/Passes/ParamTypeToInterfacePass.cs

@ -1,10 +1,13 @@ @@ -1,10 +1,13 @@
using CppSharp.AST;
using System.Linq;
using CppSharp.AST;
namespace CppSharp.Passes
{
public class ParamTypeToInterfacePass : TranslationUnitPass
{
public override bool VisitFunctionDecl(Function function)
{
if (!function.IsOperator)
{
if (function.HasIndirectReturnTypeParameter)
{
@ -15,13 +18,13 @@ namespace CppSharp.Passes @@ -15,13 +18,13 @@ namespace CppSharp.Passes
{
function.ReturnType = GetInterfaceType(function.ReturnType);
}
return base.VisitFunctionDecl(function);
}
public override bool VisitParameterDecl(Parameter parameter)
foreach (Parameter parameter in function.Parameters.Where(
p => p.Kind != ParameterKind.IndirectReturnType))
{
parameter.QualifiedType = GetInterfaceType(parameter.QualifiedType);
return base.VisitParameterDecl(parameter);
}
}
return base.VisitFunctionDecl(function);
}
private static QualifiedType GetInterfaceType(QualifiedType type)

2
src/Generator/Passes/verbs.txt

@ -6583,6 +6583,7 @@ regerminate @@ -6583,6 +6583,7 @@ regerminate
regild
regionalize
regird
register
registrate
regive
regiven
@ -7209,6 +7210,7 @@ rettore @@ -7209,6 +7210,7 @@ rettore
rettorn
retune
returf
return
retwine
retwist
retype

9
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
using System;
using System.Reflection;
using System.Reflection;
using CSharpTemp;
using NUnit.Framework;
using Foo = CSharpTemp.Foo;
@ -8,7 +7,7 @@ using Foo = CSharpTemp.Foo; @@ -8,7 +7,7 @@ using Foo = CSharpTemp.Foo;
public class CSharpTempTests
{
[Test]
public unsafe void TestIndexer()
public void TestIndexer()
{
var foo = new Foo();
@ -74,5 +73,9 @@ public class CSharpTempTests @@ -74,5 +73,9 @@ public class CSharpTempTests
Assert.That(p.value, Is.EqualTo(30));
p.prop = 50;
Assert.That(p.prop, Is.EqualTo(150));
ComplexType complexType = new ComplexType();
p.complexType = complexType;
Assert.That(p.complexType.check(), Is.EqualTo(5));
}
}

39
tests/CSharpTemp/CSharpTemp.cpp

@ -46,6 +46,30 @@ Foo& Bar::operator[](int i) @@ -46,6 +46,30 @@ Foo& Bar::operator[](int i)
return m_foo;
}
Bar Bar::operator *()
{
return *this;
}
const Bar& Bar::operator *(int m)
{
index *= m;
return *this;
}
const Bar& Bar::operator ++()
{
++index;
return *this;
}
Bar Bar::operator ++(int i)
{
Bar bar = *this;
index++;
return bar;
}
Baz::Nested::operator int() const
{
return 300;
@ -95,3 +119,18 @@ long P::prop() @@ -95,3 +119,18 @@ long P::prop()
{
return m_property + 100;
}
int ComplexType::check()
{
return 5;
}
ComplexType P::complexType()
{
return m_complexType;
}
void P::setComplexType(const ComplexType& value)
{
m_complexType = value;
}

1
tests/CSharpTemp/CSharpTemp.cs

@ -14,6 +14,7 @@ namespace CppSharp.Tests @@ -14,6 +14,7 @@ namespace CppSharp.Tests
{
driver.Options.GenerateInterfacesForMultipleInheritance = true;
driver.Options.GenerateProperties = true;
driver.Options.GenerateVirtualTables = true;
}
public static void Main(string[] args)

17
tests/CSharpTemp/CSharpTemp.h

@ -31,8 +31,13 @@ public: @@ -31,8 +31,13 @@ public:
int method();
const Foo& operator[](int i) const;
Foo& operator[](int i);
Bar operator*();
const Bar& operator*(int m);
const Bar& operator++();
Bar operator++(int i);
private:
int index;
Foo m_foo;
};
@ -86,9 +91,21 @@ public: @@ -86,9 +91,21 @@ public:
virtual long prop();
};
class DLL_API ComplexType
{
public:
int check();
};
class DLL_API P : Proprietor
{
public:
virtual void setValue(int value);
virtual long prop();
ComplexType complexType();
void setComplexType(const ComplexType& value);
private:
ComplexType m_complexType;
};

Loading…
Cancel
Save