Browse Source

Handled int and long in maps to help resolve ambiguity.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1157/head
Dimitar Dobrev 7 years ago
parent
commit
a65f91949c
  1. 3
      src/Generator/Driver.cs
  2. 51
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  3. 30
      src/Generator/Passes/CheckOperatorsOverloads.cs
  4. 82
      src/Generator/Types/Std/Stdlib.cs
  5. 11
      src/Generator/Types/TypeMap.cs
  6. 29
      src/Generator/Types/TypeMapDatabase.cs
  7. 2
      tests/CSharp/CSharp.cs
  8. 2
      tests/Common/Common.Tests.cs
  9. 16
      tests/Common/Common.cpp
  10. 4
      tests/Common/Common.h

3
src/Generator/Driver.cs

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
@ -73,7 +72,7 @@ namespace CppSharp @@ -73,7 +72,7 @@ namespace CppSharp
}
public void SetupTypeMaps() =>
Context.TypeMaps = new TypeMapDatabase(Context.ASTContext, Options);
Context.TypeMaps = new TypeMapDatabase(Context);
void OnSourceFileParsed(IEnumerable<string> files, ParserResult result)
{

51
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -133,6 +133,23 @@ namespace CppSharp.Generators.CSharp @@ -133,6 +133,23 @@ namespace CppSharp.Generators.CSharp
return $"{arrayType.Visit(this)}{arraySuffix}";
}
public override TypePrinterResult VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals)
{
TypeMap typeMap;
if (TypeMapDatabase.FindTypeMap(builtin, out typeMap))
{
var typePrinterContext = new TypePrinterContext()
{
Kind = Kind,
MarshalKind = MarshalKind,
Type = builtin,
Parameter = Parameter
};
return typeMap.CSharpSignatureType(typePrinterContext).Visit(this);
}
return base.VisitBuiltinType(builtin, quals);
}
public override TypePrinterResult VisitFunctionType(FunctionType function,
TypeQualifiers quals)
{
@ -776,6 +793,40 @@ namespace CppSharp.Generators.CSharp @@ -776,6 +793,40 @@ namespace CppSharp.Generators.CSharp
return typePrinterResult;
}
public static Type GetSignedType(uint width)
{
switch (width)
{
case 8:
return new CILType(typeof(sbyte));
case 16:
return new CILType(typeof(short));
case 32:
return new CILType(typeof(int));
case 64:
return new CILType(typeof(long));
default:
throw new System.NotSupportedException();
}
}
public static Type GetUnsignedType(uint width)
{
switch (width)
{
case 8:
return new CILType(typeof(byte));
case 16:
return new CILType(typeof(ushort));
case 32:
return new CILType(typeof(uint));
case 64:
return new CILType(typeof(ulong));
default:
throw new System.NotSupportedException();
}
}
private static bool IsValid(TemplateArgument a)
{
if (a.Type.Type == null)

30
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -185,7 +185,7 @@ namespace CppSharp.Passes @@ -185,7 +185,7 @@ namespace CppSharp.Passes
return CXXOperatorKind.None;
}
static bool IsValidOperatorOverload(Method @operator)
private bool IsValidOperatorOverload(Method @operator)
{
// These follow the order described in MSDN (Overloadable Operators).
@ -235,9 +235,31 @@ namespace CppSharp.Passes @@ -235,9 +235,31 @@ namespace CppSharp.Passes
// 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.Int;
{
Parameter parameter = @operator.Parameters.Last();
Type type = parameter.Type.Desugar();
switch (Options.GeneratorKind)
{
case GeneratorKind.CLI:
return type.IsPrimitiveType(PrimitiveType.Int);
case GeneratorKind.CSharp:
Types.TypeMap typeMap;
if (Context.TypeMaps.FindTypeMap(type, out typeMap))
{
var mappedTo = typeMap.CSharpSignatureType(
new TypePrinterContext
{
Parameter = parameter,
Type = type
});
var cilType = mappedTo as CILType;
if (cilType?.Type == typeof(int))
return true;
}
break;
}
return false;
}
// No parameters means the dereference operator - cannot be overloaded
case CXXOperatorKind.Star:

82
src/Generator/Types/Std/Stdlib.cs

@ -16,18 +16,46 @@ namespace CppSharp.Types.Std @@ -16,18 +16,46 @@ namespace CppSharp.Types.Std
public override bool IsIgnored => true;
}
[TypeMap("int", GeneratorKind = GeneratorKind.CSharp)]
public class Int : TypeMap
{
public override Type CSharpSignatureType(TypePrinterContext ctx) =>
CSharpTypePrinter.GetSignedType(Context.TargetInfo.IntWidth);
}
[TypeMap("unsigned int", GeneratorKind = GeneratorKind.CSharp)]
public class UnsignedInt : TypeMap
{
public override Type CSharpSignatureType(TypePrinterContext ctx) =>
CSharpTypePrinter.GetUnsignedType(Context.TargetInfo.IntWidth);
}
[TypeMap("long", GeneratorKind = GeneratorKind.CSharp)]
public class Long : TypeMap
{
public override Type CSharpSignatureType(TypePrinterContext ctx) =>
CSharpTypePrinter.GetSignedType(Context.TargetInfo.LongWidth);
}
[TypeMap("unsigned long", GeneratorKind = GeneratorKind.CSharp)]
public class UnsignedLong : TypeMap
{
public override Type CSharpSignatureType(TypePrinterContext ctx) =>
CSharpTypePrinter.GetUnsignedType(Context.TargetInfo.LongWidth);
}
[TypeMap("char", GeneratorKind = GeneratorKind.CSharp)]
public class Char : TypeMap
{
public override Type CSharpSignatureType(TypePrinterContext ctx)
{
return new CILType(ctx.Kind == TypePrinterContextKind.Native ||
!Options.MarshalCharAsManagedChar ? typeof(sbyte) : typeof(char));
!Context.Options.MarshalCharAsManagedChar ? typeof(sbyte) : typeof(char));
}
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
{
if (Options.MarshalCharAsManagedChar)
if (Context.Options.MarshalCharAsManagedChar)
ctx.Return.Write("global::System.Convert.ToSByte({0})",
ctx.Parameter.Name);
else
@ -36,7 +64,7 @@ namespace CppSharp.Types.Std @@ -36,7 +64,7 @@ namespace CppSharp.Types.Std
public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{
if (Options.MarshalCharAsManagedChar)
if (Context.Options.MarshalCharAsManagedChar)
ctx.Return.Write("global::System.Convert.ToChar({0})",
ctx.ReturnVarName);
else
@ -51,16 +79,6 @@ namespace CppSharp.Types.Std @@ -51,16 +79,6 @@ namespace CppSharp.Types.Std
{
return new CILType(typeof(char));
}
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
{
ctx.Return.Write(ctx.Parameter.Name);
}
public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{
ctx.Return.Write(ctx.ReturnVarName);
}
}
[TypeMap("wchar_t", GeneratorKind = GeneratorKind.CSharp)]
@ -70,16 +88,6 @@ namespace CppSharp.Types.Std @@ -70,16 +88,6 @@ namespace CppSharp.Types.Std
{
return new CILType(typeof(char));
}
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
{
ctx.Return.Write(ctx.Parameter.Name);
}
public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{
ctx.Return.Write(ctx.ReturnVarName);
}
}
[TypeMap("const char*", GeneratorKind = GeneratorKind.CSharp)]
@ -92,13 +100,13 @@ namespace CppSharp.Types.Std @@ -92,13 +100,13 @@ namespace CppSharp.Types.Std
if (ctx.Parameter == null || ctx.Parameter.Name == Helpers.ReturnIdentifier)
return new CustomType(CSharpTypePrinter.IntPtrType);
if (Options.Encoding == Encoding.ASCII)
if (Context.Options.Encoding == Encoding.ASCII)
return new CustomType("[MarshalAs(UnmanagedType.LPStr)] string");
if (Options.Encoding == Encoding.Unicode ||
Options.Encoding == Encoding.BigEndianUnicode)
if (Context.Options.Encoding == Encoding.Unicode ||
Context.Options.Encoding == Encoding.BigEndianUnicode)
return new CustomType("[MarshalAs(UnmanagedType.LPWStr)] string");
throw new System.NotSupportedException(
$"{Options.Encoding.EncodingName} is not supported yet.");
$"{Context.Options.Encoding.EncodingName} is not supported yet.");
}
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
@ -111,19 +119,19 @@ namespace CppSharp.Types.Std @@ -111,19 +119,19 @@ namespace CppSharp.Types.Std
ctx.Return.Write(ctx.Parameter.Name);
return;
}
if (Equals(Options.Encoding, Encoding.ASCII))
if (Equals(Context.Options.Encoding, Encoding.ASCII))
{
ctx.Return.Write($"Marshal.StringToHGlobalAnsi({ctx.Parameter.Name})");
return;
}
if (Equals(Options.Encoding, Encoding.Unicode) ||
Equals(Options.Encoding, Encoding.BigEndianUnicode))
if (Equals(Context.Options.Encoding, Encoding.Unicode) ||
Equals(Context.Options.Encoding, Encoding.BigEndianUnicode))
{
ctx.Return.Write($"Marshal.StringToHGlobalUni({ctx.Parameter.Name})");
return;
}
throw new System.NotSupportedException(
$"{Options.Encoding.EncodingName} is not supported yet.");
$"{Context.Options.Encoding.EncodingName} is not supported yet.");
}
public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
@ -144,7 +152,7 @@ namespace CppSharp.Types.Std @@ -144,7 +152,7 @@ namespace CppSharp.Types.Std
var encoding = isChar ? Encoding.ASCII : Encoding.Unicode;
if (Equals(encoding, Encoding.ASCII))
encoding = Options.Encoding;
encoding = Context.Options.Encoding;
if (Equals(encoding, Encoding.ASCII))
{
@ -579,15 +587,5 @@ namespace CppSharp.Types.Std @@ -579,15 +587,5 @@ namespace CppSharp.Types.Std
{
return new CILType(typeof(System.IntPtr));
}
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
{
ctx.Return.Write(ctx.Parameter.Name);
}
public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{
ctx.Return.Write(ctx.ReturnVarName);
}
}
}

11
src/Generator/Types/TypeMap.cs

@ -35,8 +35,7 @@ namespace CppSharp.Types @@ -35,8 +35,7 @@ namespace CppSharp.Types
public class TypeMap
{
public Type Type { get; set; }
public ASTContext ASTContext { get; set; }
public DriverOptions Options { get; set; }
public BindingContext Context { get; set; }
public ITypeMapDatabase TypeMapDatabase { get; set; }
public bool IsEnabled { get; set; } = true;
@ -59,12 +58,12 @@ namespace CppSharp.Types @@ -59,12 +58,12 @@ namespace CppSharp.Types
public virtual void CSharpMarshalToNative(CSharpMarshalContext ctx)
{
throw new NotImplementedException();
ctx.Return.Write(ctx.Parameter.Name);
}
public virtual void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{
throw new NotImplementedException();
ctx.Return.Write(ctx.ReturnVarName);
}
/// <summary>
@ -91,12 +90,12 @@ namespace CppSharp.Types @@ -91,12 +90,12 @@ namespace CppSharp.Types
public virtual void CLIMarshalToNative(MarshalContext ctx)
{
throw new NotImplementedException();
ctx.Return.Write(ctx.Parameter.Name);
}
public virtual void CLIMarshalToManaged(MarshalContext ctx)
{
throw new NotImplementedException();
ctx.Return.Write(ctx.ReturnVarName);
}
#endregion

29
src/Generator/Types/TypeMapDatabase.cs

@ -2,6 +2,7 @@ using System; @@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators;
using Type = CppSharp.AST.Type;
namespace CppSharp.Types
@ -10,18 +11,15 @@ namespace CppSharp.Types @@ -10,18 +11,15 @@ namespace CppSharp.Types
{
public IDictionary<string, TypeMap> TypeMaps { get; set; }
public DriverOptions Options { get; }
public TypeMapDatabase(ASTContext astContext, DriverOptions options)
public TypeMapDatabase(BindingContext bindingContext)
{
TypeMaps = new Dictionary<string, TypeMap>();
this.Options = options;
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
var types = assembly.FindDerivedTypes(typeof(TypeMap));
SetupTypeMaps(types, astContext);
SetupTypeMaps(types, bindingContext);
}
catch (System.Reflection.ReflectionTypeLoadException ex)
{
@ -31,18 +29,19 @@ namespace CppSharp.Types @@ -31,18 +29,19 @@ namespace CppSharp.Types
}
}
private void SetupTypeMaps(IEnumerable<System.Type> types, ASTContext astContext)
private void SetupTypeMaps(IEnumerable<System.Type> types,
BindingContext bindingContext)
{
foreach (var type in types)
{
var attrs = type.GetCustomAttributes(typeof(TypeMapAttribute), true);
foreach (TypeMapAttribute attr in attrs)
{
if (attr.GeneratorKind == 0 || attr.GeneratorKind == Options.GeneratorKind)
if (attr.GeneratorKind == 0 ||
attr.GeneratorKind == bindingContext.Options.GeneratorKind)
{
var typeMap = (TypeMap) Activator.CreateInstance(type);
typeMap.ASTContext = astContext;
typeMap.Options = Options;
typeMap.Context = bindingContext;
typeMap.TypeMapDatabase = this;
this.TypeMaps[attr.Type] = typeMap;
}
@ -52,6 +51,13 @@ namespace CppSharp.Types @@ -52,6 +51,13 @@ namespace CppSharp.Types
public bool FindTypeMap(Type type, out TypeMap typeMap)
{
if (type.Desugar(resolveTemplateSubstitution: false) is
TemplateParameterSubstitutionType)
{
typeMap = null;
return false;
}
if (typeMaps.ContainsKey(type))
{
typeMap = typeMaps[type];
@ -78,8 +84,9 @@ namespace CppSharp.Types @@ -78,8 +84,9 @@ namespace CppSharp.Types
}
Type desugared = type.Desugar();
bool printExtra = desugared.GetPointee() != null &&
desugared.GetFinalPointee().Desugar().IsPrimitiveType();
desugared = (desugared.GetFinalPointee() ?? desugared).Desugar();
bool printExtra = desugared.IsPrimitiveType() ||
(desugared.GetFinalPointee() ?? desugared).Desugar().IsPrimitiveType();
var typePrinter = new CppTypePrinter
{
PrintTypeQualifiers = printExtra,

2
tests/CSharp/CSharp.cs

@ -156,7 +156,7 @@ namespace CppSharp.Tests @@ -156,7 +156,7 @@ namespace CppSharp.Tests
public override Type CSharpSignatureType(TypePrinterContext ctx)
{
return new TagType(flags ?? (flags = ASTContext.FindEnum("Flags").First()));
return new TagType(flags ?? (flags = Context.ASTContext.FindEnum("Flags").First()));
}
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)

2
tests/Common/Common.Tests.cs

@ -56,6 +56,8 @@ public class CommonTests : GeneratorTestFixture @@ -56,6 +56,8 @@ public class CommonTests : GeneratorTestFixture
itemsDifferByCase = ItemsDifferByCase.CaseA;
itemsDifferByCase.GetHashCode();
Common.SMallFollowedByCapital();
Common.IntegerOverload(0);
Common.IntegerOverload((uint) 0);
using (new DerivedFromSecondaryBaseWithIgnoredVirtualMethod()) { }
#pragma warning restore 0168

16
tests/Common/Common.cpp

@ -975,3 +975,19 @@ void DerivedFromSecondaryBaseWithIgnoredVirtualMethod::generated() @@ -975,3 +975,19 @@ void DerivedFromSecondaryBaseWithIgnoredVirtualMethod::generated()
void DerivedFromSecondaryBaseWithIgnoredVirtualMethod::ignored(const IgnoredType& ignoredParam)
{
}
void integerOverload(int i)
{
}
void integerOverload(unsigned int i)
{
}
void integerOverload(long i)
{
}
void integerOverload(unsigned long i)
{
}

4
tests/Common/Common.h

@ -1471,3 +1471,7 @@ template<int N> using TypeAlias = InvokeGenSeq<DerivedTypeAlias<N>>; @@ -1471,3 +1471,7 @@ template<int N> using TypeAlias = InvokeGenSeq<DerivedTypeAlias<N>>;
template<int N>
struct DerivedTypeAlias : TypeAlias<N / 2> {};
DLL_API void integerOverload(int i);
DLL_API void integerOverload(unsigned int i);
DLL_API void integerOverload(long i);
DLL_API void integerOverload(unsigned long i);

Loading…
Cancel
Save