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

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

@ -133,6 +133,23 @@ namespace CppSharp.Generators.CSharp
return $"{arrayType.Visit(this)}{arraySuffix}"; 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, public override TypePrinterResult VisitFunctionType(FunctionType function,
TypeQualifiers quals) TypeQualifiers quals)
{ {
@ -776,6 +793,40 @@ namespace CppSharp.Generators.CSharp
return typePrinterResult; 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) private static bool IsValid(TemplateArgument a)
{ {
if (a.Type.Type == null) if (a.Type.Type == null)

30
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -185,7 +185,7 @@ namespace CppSharp.Passes
return CXXOperatorKind.None; return CXXOperatorKind.None;
} }
static bool IsValidOperatorOverload(Method @operator) private bool IsValidOperatorOverload(Method @operator)
{ {
// These follow the order described in MSDN (Overloadable Operators). // These follow the order described in MSDN (Overloadable Operators).
@ -235,9 +235,31 @@ namespace CppSharp.Passes
// Bitwise shift operators can only be overloaded if the second parameter is int // Bitwise shift operators can only be overloaded if the second parameter is int
case CXXOperatorKind.LessLess: case CXXOperatorKind.LessLess:
case CXXOperatorKind.GreaterGreater: case CXXOperatorKind.GreaterGreater:
PrimitiveType primitiveType; {
return @operator.Parameters.Last().Type.IsPrimitiveType(out primitiveType) && Parameter parameter = @operator.Parameters.Last();
primitiveType == PrimitiveType.Int; 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 // No parameters means the dereference operator - cannot be overloaded
case CXXOperatorKind.Star: case CXXOperatorKind.Star:

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

@ -16,18 +16,46 @@ namespace CppSharp.Types.Std
public override bool IsIgnored => true; 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)] [TypeMap("char", GeneratorKind = GeneratorKind.CSharp)]
public class Char : TypeMap public class Char : TypeMap
{ {
public override Type CSharpSignatureType(TypePrinterContext ctx) public override Type CSharpSignatureType(TypePrinterContext ctx)
{ {
return new CILType(ctx.Kind == TypePrinterContextKind.Native || 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) public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
{ {
if (Options.MarshalCharAsManagedChar) if (Context.Options.MarshalCharAsManagedChar)
ctx.Return.Write("global::System.Convert.ToSByte({0})", ctx.Return.Write("global::System.Convert.ToSByte({0})",
ctx.Parameter.Name); ctx.Parameter.Name);
else else
@ -36,7 +64,7 @@ namespace CppSharp.Types.Std
public override void CSharpMarshalToManaged(CSharpMarshalContext ctx) public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{ {
if (Options.MarshalCharAsManagedChar) if (Context.Options.MarshalCharAsManagedChar)
ctx.Return.Write("global::System.Convert.ToChar({0})", ctx.Return.Write("global::System.Convert.ToChar({0})",
ctx.ReturnVarName); ctx.ReturnVarName);
else else
@ -51,16 +79,6 @@ namespace CppSharp.Types.Std
{ {
return new CILType(typeof(char)); 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)] [TypeMap("wchar_t", GeneratorKind = GeneratorKind.CSharp)]
@ -70,16 +88,6 @@ namespace CppSharp.Types.Std
{ {
return new CILType(typeof(char)); 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)] [TypeMap("const char*", GeneratorKind = GeneratorKind.CSharp)]
@ -92,13 +100,13 @@ namespace CppSharp.Types.Std
if (ctx.Parameter == null || ctx.Parameter.Name == Helpers.ReturnIdentifier) if (ctx.Parameter == null || ctx.Parameter.Name == Helpers.ReturnIdentifier)
return new CustomType(CSharpTypePrinter.IntPtrType); return new CustomType(CSharpTypePrinter.IntPtrType);
if (Options.Encoding == Encoding.ASCII) if (Context.Options.Encoding == Encoding.ASCII)
return new CustomType("[MarshalAs(UnmanagedType.LPStr)] string"); return new CustomType("[MarshalAs(UnmanagedType.LPStr)] string");
if (Options.Encoding == Encoding.Unicode || if (Context.Options.Encoding == Encoding.Unicode ||
Options.Encoding == Encoding.BigEndianUnicode) Context.Options.Encoding == Encoding.BigEndianUnicode)
return new CustomType("[MarshalAs(UnmanagedType.LPWStr)] string"); return new CustomType("[MarshalAs(UnmanagedType.LPWStr)] string");
throw new System.NotSupportedException( 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) public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
@ -111,19 +119,19 @@ namespace CppSharp.Types.Std
ctx.Return.Write(ctx.Parameter.Name); ctx.Return.Write(ctx.Parameter.Name);
return; return;
} }
if (Equals(Options.Encoding, Encoding.ASCII)) if (Equals(Context.Options.Encoding, Encoding.ASCII))
{ {
ctx.Return.Write($"Marshal.StringToHGlobalAnsi({ctx.Parameter.Name})"); ctx.Return.Write($"Marshal.StringToHGlobalAnsi({ctx.Parameter.Name})");
return; return;
} }
if (Equals(Options.Encoding, Encoding.Unicode) || if (Equals(Context.Options.Encoding, Encoding.Unicode) ||
Equals(Options.Encoding, Encoding.BigEndianUnicode)) Equals(Context.Options.Encoding, Encoding.BigEndianUnicode))
{ {
ctx.Return.Write($"Marshal.StringToHGlobalUni({ctx.Parameter.Name})"); ctx.Return.Write($"Marshal.StringToHGlobalUni({ctx.Parameter.Name})");
return; return;
} }
throw new System.NotSupportedException( 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) public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
@ -144,7 +152,7 @@ namespace CppSharp.Types.Std
var encoding = isChar ? Encoding.ASCII : Encoding.Unicode; var encoding = isChar ? Encoding.ASCII : Encoding.Unicode;
if (Equals(encoding, Encoding.ASCII)) if (Equals(encoding, Encoding.ASCII))
encoding = Options.Encoding; encoding = Context.Options.Encoding;
if (Equals(encoding, Encoding.ASCII)) if (Equals(encoding, Encoding.ASCII))
{ {
@ -579,15 +587,5 @@ namespace CppSharp.Types.Std
{ {
return new CILType(typeof(System.IntPtr)); 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
public class TypeMap public class TypeMap
{ {
public Type Type { get; set; } public Type Type { get; set; }
public ASTContext ASTContext { get; set; } public BindingContext Context { get; set; }
public DriverOptions Options { get; set; }
public ITypeMapDatabase TypeMapDatabase { get; set; } public ITypeMapDatabase TypeMapDatabase { get; set; }
public bool IsEnabled { get; set; } = true; public bool IsEnabled { get; set; } = true;
@ -59,12 +58,12 @@ namespace CppSharp.Types
public virtual void CSharpMarshalToNative(CSharpMarshalContext ctx) public virtual void CSharpMarshalToNative(CSharpMarshalContext ctx)
{ {
throw new NotImplementedException(); ctx.Return.Write(ctx.Parameter.Name);
} }
public virtual void CSharpMarshalToManaged(CSharpMarshalContext ctx) public virtual void CSharpMarshalToManaged(CSharpMarshalContext ctx)
{ {
throw new NotImplementedException(); ctx.Return.Write(ctx.ReturnVarName);
} }
/// <summary> /// <summary>
@ -91,12 +90,12 @@ namespace CppSharp.Types
public virtual void CLIMarshalToNative(MarshalContext ctx) public virtual void CLIMarshalToNative(MarshalContext ctx)
{ {
throw new NotImplementedException(); ctx.Return.Write(ctx.Parameter.Name);
} }
public virtual void CLIMarshalToManaged(MarshalContext ctx) public virtual void CLIMarshalToManaged(MarshalContext ctx)
{ {
throw new NotImplementedException(); ctx.Return.Write(ctx.ReturnVarName);
} }
#endregion #endregion

29
src/Generator/Types/TypeMapDatabase.cs

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

2
tests/CSharp/CSharp.cs

@ -156,7 +156,7 @@ namespace CppSharp.Tests
public override Type CSharpSignatureType(TypePrinterContext ctx) 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) public override void CSharpMarshalToNative(CSharpMarshalContext ctx)

2
tests/Common/Common.Tests.cs

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

16
tests/Common/Common.cpp

@ -975,3 +975,19 @@ void DerivedFromSecondaryBaseWithIgnoredVirtualMethod::generated()
void DerivedFromSecondaryBaseWithIgnoredVirtualMethod::ignored(const IgnoredType& ignoredParam) 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>>;
template<int N> template<int N>
struct DerivedTypeAlias : TypeAlias<N / 2> {}; 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