Browse Source

Merge pull request #225 from azeno/master

Const pointer and indexer fixes
pull/227/merge
João Matos 11 years ago
parent
commit
90dd38e42c
  1. 66
      src/AST/TypeExtensions.cs
  2. 20
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  3. 24
      src/Generator/Generators/CLI/CLIMarshal.cs
  4. 48
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  5. 780
      src/Generator/Generators/CLI/CLITypePrinter.cs
  6. 4
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  7. 21
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  8. 2
      src/Generator/Passes/CheckIgnoredDecls.cs
  9. 16
      src/Generator/Passes/CheckOperatorsOverloads.cs
  10. 11
      src/Generator/Types/Types.cs
  11. 24
      tests/Basic/Basic.Tests.cs
  12. 5
      tests/Basic/Basic.cpp
  13. 27
      tests/Basic/Basic.h

66
src/AST/TypeExtensions.cs

@ -90,26 +90,19 @@ @@ -90,26 +90,19 @@
if (ptr == null)
return false;
return ptr.Pointee.IsPrimitiveType(primitive);
}
public static bool IsPointerTo<T>(this Type t, out T type) where T : Type
{
var ptr = t as PointerType;
if (ptr == null)
{
var functionPointer = t as MemberPointerType;
if (functionPointer != null)
{
type = functionPointer.Pointee as T;
return type != null;
}
type = null;
return false;
}
type = ptr.Pointee as T;
return type != null;
}
public static bool IsPointerTo<T>(this Type t, out T type) where T : Type
{
var pointee = t.GetPointee();
type = pointee as T;
if (type == null)
{
var attributedType = pointee as AttributedType;
if (attributedType != null)
type = attributedType.Modified.Type as T;
}
return type != null;
}
public static bool IsTagDecl<T>(this Type t, out T decl) where T : Declaration
@ -154,6 +147,39 @@ @@ -154,6 +147,39 @@
}
return t;
}
/// <summary>
/// If t is a pointer type the type pointed to by t will be returned.
/// Otherwise null.
/// </summary>
public static Type GetPointee(this Type t)
{
var ptr = t as PointerType;
if (ptr != null)
return ptr.Pointee;
var memberPtr = t as MemberPointerType;
if (memberPtr != null)
return memberPtr.Pointee;
return null;
}
/// <summary>
/// If t is a pointer type the type pointed to by t will be returned
/// after fully dereferencing it. Otherwise null.
/// For example int** -> int.
/// </summary>
public static Type GetFinalPointee(this Type t)
{
var finalPointee = t.GetPointee();
var pointee = finalPointee;
while (pointee != null)
{
pointee = pointee.GetPointee();
if (pointee != null)
finalPointee = pointee;
}
return finalPointee;
}
}
}

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

@ -615,16 +615,19 @@ namespace CppSharp.Generators.CLI @@ -615,16 +615,19 @@ namespace CppSharp.Generators.CLI
public void GenerateIndexer(Property property)
{
var type = property.QualifiedType.Visit(TypePrinter);
var type = property.QualifiedType.Visit(TypePrinter);
var getter = property.GetMethod;
var indexParameter = getter.Parameters[0];
var indexParameterType = indexParameter.QualifiedType.Visit(TypePrinter);
WriteLine("property {0} default[int]", type);
WriteLine("property {0} default[{1}]", type, indexParameterType);
WriteStartBraceIndent();
if (property.HasGetter)
WriteLine("{0} get(int index);", type);
if (property.HasGetter)
WriteLine("{0} get({1} {2});", type, indexParameterType, indexParameter.Name);
if (property.HasSetter)
WriteLine("void set(int index, {0});", type);
if (property.HasSetter)
WriteLine("void set({1} {2}, {0} value);", type, indexParameterType, indexParameter.Name);
WriteCloseBraceIndent();
}
@ -635,7 +638,10 @@ namespace CppSharp.Generators.CLI @@ -635,7 +638,10 @@ namespace CppSharp.Generators.CLI
return;
PushBlock(CLIBlockKind.Property, property);
var type = property.QualifiedType.Visit(TypePrinter);
var type = property.QualifiedType.Visit(TypePrinter);
if (property.IsStatic)
Write("static ");
if (property.IsIndexer)
{

24
src/Generator/Generators/CLI/CLIMarshal.cs

@ -90,12 +90,16 @@ namespace CppSharp.Generators.CLI @@ -90,12 +90,16 @@ namespace CppSharp.Generators.CLI
}
if (pointee.IsPrimitiveType(out primitive))
{
{
var returnVarName = Context.ReturnVarName;
if (quals.IsConst != Context.ReturnType.Qualifiers.IsConst)
returnVarName = string.Format("const_cast<{0}>({1})",
Context.ReturnType, Context.ReturnVarName);
if (pointer.Pointee is TypedefType)
Context.Return.Write("reinterpret_cast<{0}>({1})", pointer,
Context.ReturnVarName);
else
Context.Return.Write(Context.ReturnVarName);
Context.Return.Write("reinterpret_cast<{0}>({1})", pointer,
returnVarName);
else
Context.Return.Write(returnVarName);
return true;
}
@ -436,10 +440,10 @@ namespace CppSharp.Generators.CLI @@ -436,10 +440,10 @@ namespace CppSharp.Generators.CLI
if (Context.Function == null)
Context.Return.Write("&");
return pointee.Visit(this, quals);
}
PrimitiveType primitive;
if (pointee.IsPrimitiveType(out primitive))
}
var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{
var cppTypePrinter = new CppTypePrinter(Context.Driver.TypeDatabase);
var cppTypeName = pointer.Visit(cppTypePrinter, quals);
@ -506,7 +510,7 @@ namespace CppSharp.Generators.CLI @@ -506,7 +510,7 @@ namespace CppSharp.Generators.CLI
}
PrimitiveType primitive;
if (decl.Type.Desugar().IsPrimitiveType(out primitive))
if (decl.Type.IsPrimitiveType(out primitive))
{
Context.Return.Write("(::{0})", typedef.Declaration.QualifiedOriginalName);
}

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

@ -329,36 +329,37 @@ namespace CppSharp.Generators.CLI @@ -329,36 +329,37 @@ namespace CppSharp.Generators.CLI
GeneratePropertyGetter(property.GetMethod, realOwner, property.Name,
property.Type);
if (property.HasSetter)
GeneratePropertySetter(property.SetMethod, realOwner, property.Name,
property.Type);
if (property.HasSetter)
if (property.IsIndexer)
GeneratePropertySetter(property.SetMethod, realOwner, property.Name,
property.Type, property.GetMethod.Parameters[0]);
else
GeneratePropertySetter(property.SetMethod, realOwner, property.Name,
property.Type);
}
PopBlock();
}
private void GeneratePropertySetter<T>(T decl, Class @class, string name, Type type)
}
private void GeneratePropertySetter<T>(T decl, Class @class, string name, Type type, Parameter indexParameter = null)
where T : Declaration, ITypedDecl
{
if (decl == null)
return;
return;
var method = decl as Method;
var isIndexer = method != null &&
method.OperatorKind == CXXOperatorKind.Subscript;
var args = new List<string>();
if (isIndexer)
args.Add("int index");
var args = new List<string>();
var isIndexer = indexParameter != null;
if (isIndexer)
args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name));
var function = decl as Function;
var argName = function != null ? function.Parameters[0].Name : "value";
var argName = function != null && !isIndexer ? function.Parameters[0].Name : "value";
args.Add(string.Format("{0} {1}", type, argName));
WriteLine("void {0}::{1}::set({2})", QualifiedIdentifier(@class),
name, string.Join(", ", args));
WriteStartBraceIndent();
WriteStartBraceIndent();
if (decl is Function && !isIndexer)
{
var func = decl as Function;
@ -397,7 +398,7 @@ namespace CppSharp.Generators.CLI @@ -397,7 +398,7 @@ namespace CppSharp.Generators.CLI
@class.QualifiedOriginalName, decl.OriginalName);
if (isIndexer)
variable += "(index)";
variable += string.Format("({0})", indexParameter.Name);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
@ -419,9 +420,12 @@ namespace CppSharp.Generators.CLI @@ -419,9 +420,12 @@ namespace CppSharp.Generators.CLI
var isIndexer = method != null &&
method.OperatorKind == CXXOperatorKind.Subscript;
var args = new List<string>();
if (isIndexer)
args.Add("int index");
var args = new List<string>();
if (isIndexer)
{
var indexParameter = method.Parameters[0];
args.Add(string.Format("{0} {1}", indexParameter.Type, indexParameter.Name));
}
WriteLine("{0} {1}::{2}::get({3})", type, QualifiedIdentifier(@class),
name, string.Join(", ", args));
@ -966,7 +970,7 @@ namespace CppSharp.Generators.CLI @@ -966,7 +970,7 @@ namespace CppSharp.Generators.CLI
if (Driver.Options.MarshalCharAsManagedChar)
{
foreach (var param in method.Parameters.Where(
p => p.Type.Desugar().IsPrimitiveType(PrimitiveType.Int8)))
p => p.Type.IsPrimitiveType(PrimitiveType.Int8)))
{
WriteLine("if ({0} < System::Char::MinValue || {0} > System::SByte::MaxValue)", param.Name);
WriteLineIndent(

780
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -1,386 +1,394 @@ @@ -1,386 +1,394 @@
using System;
using System.Collections.Generic;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Types;
using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CLI
{
public class CLITypePrinterContext : TypePrinterContext
{
public CLITypePrinterContext()
{
}
public CLITypePrinterContext(TypePrinterContextKind kind)
: base(kind)
{
}
}
public class CLITypePrinter : ITypePrinter<string>, IDeclVisitor<string>
{
public Driver Driver { get; set; }
public CLITypePrinterContext Context { get; set; }
readonly ITypeMapDatabase TypeMapDatabase;
readonly DriverOptions Options;
public CLITypePrinter(Driver driver)
{
Driver = driver;
TypeMapDatabase = driver.TypeDatabase;
Options = driver.Options;
Context = new CLITypePrinterContext();
}
public CLITypePrinter(Driver driver, CLITypePrinterContext context)
: this(driver)
{
Context = context;
}
public string VisitTagType(TagType tag, TypeQualifiers quals)
{
TypeMap typeMap = null;
if (TypeMapDatabase.FindTypeMap(tag, out typeMap))
{
typeMap.Type = tag;
Context.Type = tag;
return typeMap.CLISignature(Context);
}
Declaration decl = tag.Declaration;
if (decl == null)
return string.Empty;
return VisitDeclaration(decl, quals);
}
public string VisitArrayType(ArrayType array, TypeQualifiers quals)
{
return string.Format("cli::array<{0}>^", array.Type.Visit(this));
}
public string VisitFunctionType(FunctionType function, TypeQualifiers quals)
{
var arguments = function.Parameters;
var returnType = function.ReturnType;
var args = string.Empty;
if (arguments.Count > 0)
args = VisitParameters(function.Parameters, hasNames: false);
if (returnType.Type.IsPrimitiveType(PrimitiveType.Void))
{
if (!string.IsNullOrEmpty(args))
args = string.Format("<{0}>", args);
return string.Format("System::Action{0}", args);
}
if (!string.IsNullOrEmpty(args))
args = string.Format(", {0}", args);
return string.Format("System::Func<{0}{1}>", returnType.Visit(this), args);
}
public string VisitParameters(IEnumerable<Parameter> @params,
bool hasNames)
{
var args = new List<string>();
foreach (var param in @params)
args.Add(VisitParameter(param, hasNames));
return string.Join(", ", args);
}
public string VisitParameter(Parameter param, bool hasName = true)
{
Context.Parameter = param;
var type = param.Type.Visit(this, param.QualifiedType.Qualifiers);
Context.Parameter = null;
var str = string.Empty;
if(param.Usage == ParameterUsage.Out)
str += "[System::Runtime::InteropServices::Out] ";
str += type;
if(param.Usage == ParameterUsage.Out ||
param.Usage == ParameterUsage.InOut)
str += "%";
if (hasName && !string.IsNullOrEmpty(param.Name))
str += " " + param.Name;
return str;
}
public string VisitDelegate(FunctionType function)
{
return string.Format("delegate {0} {{0}}({1})",
function.ReturnType.Visit(this),
VisitParameters(function.Parameters, hasNames: true));
}
public string VisitPointerType(PointerType pointer, TypeQualifiers quals)
{
var pointee = pointer.Pointee.Desugar();
if (pointee is FunctionType)
{
var function = pointee as FunctionType;
return string.Format("{0}^", function.Visit(this, quals));
}
if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst)
{
return "System::String^";
}
PrimitiveType primitive;
if (pointee.IsPrimitiveType(out primitive))
{
var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut))
return VisitPrimitiveType(primitive);
return VisitPrimitiveType(primitive, quals) + "*";
}
Enumeration @enum;
if (pointee.IsTagDecl(out @enum))
{
var typeName = @enum.Visit(this);
return string.Format("{0}*", typeName);
}
return pointee.Visit(this, quals);
}
public string VisitMemberPointerType(MemberPointerType member,
TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals)
{
return VisitPrimitiveType(builtin.Type);
}
public string VisitPrimitiveType(PrimitiveType primitive)
{
switch (primitive)
{
case PrimitiveType.Bool: return "bool";
case PrimitiveType.Void: return "void";
case PrimitiveType.Char16:
case PrimitiveType.WideChar: return "System::Char";
case PrimitiveType.Int8: return Options.MarshalCharAsManagedChar ? "System::Char" : "char";
case PrimitiveType.UInt8: return "unsigned char";
case PrimitiveType.Int16: return "short";
case PrimitiveType.UInt16: return "unsigned short";
case PrimitiveType.Int32: return "int";
case PrimitiveType.UInt32: return "unsigned int";
case PrimitiveType.Int64: return "long long";
case PrimitiveType.UInt64: return "unsigned long long";
case PrimitiveType.Float: return "float";
case PrimitiveType.Double: return "double";
case PrimitiveType.IntPtr: return "IntPtr";
case PrimitiveType.UIntPtr: return "UIntPtr";
}
throw new NotSupportedException();
}
public string VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
{
var decl = typedef.Declaration;
TypeMap typeMap = null;
if (TypeMapDatabase.FindTypeMap(decl, out typeMap))
{
typeMap.Type = typedef;
Context.Type = typedef;
return typeMap.CLISignature(Context);
}
FunctionType func;
if (decl.Type.IsPointerTo<FunctionType>(out func))
{
// TODO: Use SafeIdentifier()
return string.Format("{0}^", VisitDeclaration(decl));
}
return decl.Type.Visit(this);
}
public string VisitAttributedType(AttributedType attributed, TypeQualifiers quals)
{
return attributed.Modified.Visit(this);
}
public string VisitDecayedType(DecayedType decayed, TypeQualifiers quals)
{
return decayed.Decayed.Visit(this);
}
public string VisitTemplateSpecializationType(TemplateSpecializationType template,
TypeQualifiers quals)
{
var decl = template.Template.TemplatedDecl;
TypeMap typeMap = null;
if (TypeMapDatabase.FindTypeMap(template, out typeMap))
{
typeMap.Declaration = decl;
typeMap.Type = template;
Context.Type = template;
return typeMap.CLISignature(Context);
}
return decl.Name;
}
public string VisitTemplateParameterType(TemplateParameterType param,
TypeQualifiers quals)
{
return param.Parameter.Name;
}
public string VisitTemplateParameterSubstitutionType(
TemplateParameterSubstitutionType param, TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitInjectedClassNameType(InjectedClassNameType injected, TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitDependentNameType(DependentNameType dependent, TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitPackExpansionType(PackExpansionType packExpansionType, TypeQualifiers quals)
{
return string.Empty;
}
public string VisitCILType(CILType type, TypeQualifiers quals)
{
return type.Type.FullName.Replace(".", "::") + "^";
}
public string VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals)
{
return VisitPrimitiveType(type);
}
public string VisitDeclaration(Declaration decl, TypeQualifiers quals)
{
return VisitDeclaration(decl);
}
public string VisitDeclaration(Declaration decl)
{
var names = new List<string>();
if (Options.GenerateLibraryNamespace)
names.Add(Driver.Options.OutputNamespace);
if (!string.IsNullOrEmpty(decl.Namespace.QualifiedName))
names.Add(decl.Namespace.QualifiedName);
names.Add(decl.Visit(this));
return string.Join("::", names);
}
public string VisitClassDecl(Class @class)
{
if (@class.CompleteDeclaration != null)
return VisitClassDecl(@class.CompleteDeclaration as Class);
return string.Format("{0}{1}", @class.Name, @class.IsRefType ? "^"
: string.Empty);
}
public string VisitFieldDecl(Field field)
{
throw new NotImplementedException();
}
public string VisitFunctionDecl(Function function)
{
throw new NotImplementedException();
}
public string VisitMethodDecl(Method method)
{
throw new NotImplementedException();
}
public string VisitParameterDecl(Parameter parameter)
{
throw new NotImplementedException();
}
public string VisitTypedefDecl(TypedefDecl typedef)
{
return typedef.Name;
}
public string VisitEnumDecl(Enumeration @enum)
{
return @enum.Name;
}
public string VisitVariableDecl(Variable variable)
{
throw new NotImplementedException();
}
public string VisitClassTemplateDecl(ClassTemplate template)
{
throw new NotImplementedException();
}
public string VisitFunctionTemplateDecl(FunctionTemplate template)
{
throw new NotImplementedException();
}
public string VisitMacroDefinition(MacroDefinition macro)
{
throw new NotImplementedException();
}
public string VisitNamespace(Namespace @namespace)
{
throw new NotImplementedException();
}
public string VisitEvent(Event @event)
{
throw new NotImplementedException();
}
public string VisitProperty(Property property)
{
throw new NotImplementedException();
}
public string ToString(Type type)
{
return type.Visit(this);
}
}
}
using System;
using System.Collections.Generic;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Types;
using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CLI
{
public class CLITypePrinterContext : TypePrinterContext
{
public CLITypePrinterContext()
{
}
public CLITypePrinterContext(TypePrinterContextKind kind)
: base(kind)
{
}
}
public class CLITypePrinter : ITypePrinter<string>, IDeclVisitor<string>
{
public Driver Driver { get; set; }
public CLITypePrinterContext Context { get; set; }
readonly ITypeMapDatabase TypeMapDatabase;
readonly DriverOptions Options;
public CLITypePrinter(Driver driver)
{
Driver = driver;
TypeMapDatabase = driver.TypeDatabase;
Options = driver.Options;
Context = new CLITypePrinterContext();
}
public CLITypePrinter(Driver driver, CLITypePrinterContext context)
: this(driver)
{
Context = context;
}
public string VisitTagType(TagType tag, TypeQualifiers quals)
{
TypeMap typeMap = null;
if (TypeMapDatabase.FindTypeMap(tag, out typeMap))
{
typeMap.Type = tag;
Context.Type = tag;
return typeMap.CLISignature(Context);
}
Declaration decl = tag.Declaration;
if (decl == null)
return string.Empty;
return VisitDeclaration(decl, quals);
}
public string VisitArrayType(ArrayType array, TypeQualifiers quals)
{
return string.Format("cli::array<{0}>^", array.Type.Visit(this));
}
public string VisitFunctionType(FunctionType function, TypeQualifiers quals)
{
var arguments = function.Parameters;
var returnType = function.ReturnType;
var args = string.Empty;
if (arguments.Count > 0)
args = VisitParameters(function.Parameters, hasNames: false);
if (returnType.Type.IsPrimitiveType(PrimitiveType.Void))
{
if (!string.IsNullOrEmpty(args))
args = string.Format("<{0}>", args);
return string.Format("System::Action{0}", args);
}
if (!string.IsNullOrEmpty(args))
args = string.Format(", {0}", args);
return string.Format("System::Func<{0}{1}>", returnType.Visit(this), args);
}
public string VisitParameters(IEnumerable<Parameter> @params,
bool hasNames)
{
var args = new List<string>();
foreach (var param in @params)
args.Add(VisitParameter(param, hasNames));
return string.Join(", ", args);
}
public string VisitParameter(Parameter param, bool hasName = true)
{
Context.Parameter = param;
var type = param.Type.Visit(this, param.QualifiedType.Qualifiers);
Context.Parameter = null;
var str = string.Empty;
if(param.Usage == ParameterUsage.Out)
str += "[System::Runtime::InteropServices::Out] ";
str += type;
if(param.Usage == ParameterUsage.Out ||
param.Usage == ParameterUsage.InOut)
str += "%";
if (hasName && !string.IsNullOrEmpty(param.Name))
str += " " + param.Name;
return str;
}
public string VisitDelegate(FunctionType function)
{
return string.Format("delegate {0} {{0}}({1})",
function.ReturnType.Visit(this),
VisitParameters(function.Parameters, hasNames: true));
}
public string VisitPointerType(PointerType pointer, TypeQualifiers quals)
{
var pointee = pointer.Pointee.Desugar();
if (pointee is FunctionType)
{
var function = pointee as FunctionType;
return string.Format("{0}^", function.Visit(this, quals));
}
if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst)
{
return "System::String^";
}
// From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
// Any of the following types may be a pointer type:
// * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
// * Any enum type.
// * Any pointer type.
// * Any user-defined struct type that contains fields of unmanaged types only.
var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{
// Skip one indirection if passed by reference
var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut)
&& pointee == finalPointee)
return pointee.Visit(this, quals);
return pointee.Visit(this, quals) + "*";
}
Enumeration @enum;
if (pointee.IsTagDecl(out @enum))
{
var typeName = @enum.Visit(this);
return string.Format("{0}*", typeName);
}
return pointee.Visit(this, quals);
}
public string VisitMemberPointerType(MemberPointerType member,
TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals)
{
return VisitPrimitiveType(builtin.Type);
}
public string VisitPrimitiveType(PrimitiveType primitive)
{
switch (primitive)
{
case PrimitiveType.Bool: return "bool";
case PrimitiveType.Void: return "void";
case PrimitiveType.Char16:
case PrimitiveType.WideChar: return "System::Char";
case PrimitiveType.Int8: return Options.MarshalCharAsManagedChar ? "System::Char" : "char";
case PrimitiveType.UInt8: return "unsigned char";
case PrimitiveType.Int16: return "short";
case PrimitiveType.UInt16: return "unsigned short";
case PrimitiveType.Int32: return "int";
case PrimitiveType.UInt32: return "unsigned int";
case PrimitiveType.Int64: return "long long";
case PrimitiveType.UInt64: return "unsigned long long";
case PrimitiveType.Float: return "float";
case PrimitiveType.Double: return "double";
case PrimitiveType.IntPtr: return "IntPtr";
case PrimitiveType.UIntPtr: return "UIntPtr";
}
throw new NotSupportedException();
}
public string VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
{
var decl = typedef.Declaration;
TypeMap typeMap = null;
if (TypeMapDatabase.FindTypeMap(decl, out typeMap))
{
typeMap.Type = typedef;
Context.Type = typedef;
return typeMap.CLISignature(Context);
}
FunctionType func;
if (decl.Type.IsPointerTo<FunctionType>(out func))
{
// TODO: Use SafeIdentifier()
return string.Format("{0}^", VisitDeclaration(decl));
}
return decl.Type.Visit(this);
}
public string VisitAttributedType(AttributedType attributed, TypeQualifiers quals)
{
return attributed.Modified.Visit(this);
}
public string VisitDecayedType(DecayedType decayed, TypeQualifiers quals)
{
return decayed.Decayed.Visit(this);
}
public string VisitTemplateSpecializationType(TemplateSpecializationType template,
TypeQualifiers quals)
{
var decl = template.Template.TemplatedDecl;
TypeMap typeMap = null;
if (TypeMapDatabase.FindTypeMap(template, out typeMap))
{
typeMap.Declaration = decl;
typeMap.Type = template;
Context.Type = template;
return typeMap.CLISignature(Context);
}
return decl.Name;
}
public string VisitTemplateParameterType(TemplateParameterType param,
TypeQualifiers quals)
{
return param.Parameter.Name;
}
public string VisitTemplateParameterSubstitutionType(
TemplateParameterSubstitutionType param, TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitInjectedClassNameType(InjectedClassNameType injected, TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitDependentNameType(DependentNameType dependent, TypeQualifiers quals)
{
throw new NotImplementedException();
}
public string VisitPackExpansionType(PackExpansionType packExpansionType, TypeQualifiers quals)
{
return string.Empty;
}
public string VisitCILType(CILType type, TypeQualifiers quals)
{
return type.Type.FullName.Replace(".", "::") + "^";
}
public string VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals)
{
return VisitPrimitiveType(type);
}
public string VisitDeclaration(Declaration decl, TypeQualifiers quals)
{
return VisitDeclaration(decl);
}
public string VisitDeclaration(Declaration decl)
{
var names = new List<string>();
if (Options.GenerateLibraryNamespace)
names.Add(Driver.Options.OutputNamespace);
if (!string.IsNullOrEmpty(decl.Namespace.QualifiedName))
names.Add(decl.Namespace.QualifiedName);
names.Add(decl.Visit(this));
return string.Join("::", names);
}
public string VisitClassDecl(Class @class)
{
if (@class.CompleteDeclaration != null)
return VisitClassDecl(@class.CompleteDeclaration as Class);
return string.Format("{0}{1}", @class.Name, @class.IsRefType ? "^"
: string.Empty);
}
public string VisitFieldDecl(Field field)
{
throw new NotImplementedException();
}
public string VisitFunctionDecl(Function function)
{
throw new NotImplementedException();
}
public string VisitMethodDecl(Method method)
{
throw new NotImplementedException();
}
public string VisitParameterDecl(Parameter parameter)
{
throw new NotImplementedException();
}
public string VisitTypedefDecl(TypedefDecl typedef)
{
return typedef.Name;
}
public string VisitEnumDecl(Enumeration @enum)
{
return @enum.Name;
}
public string VisitVariableDecl(Variable variable)
{
throw new NotImplementedException();
}
public string VisitClassTemplateDecl(ClassTemplate template)
{
throw new NotImplementedException();
}
public string VisitFunctionTemplateDecl(FunctionTemplate template)
{
throw new NotImplementedException();
}
public string VisitMacroDefinition(MacroDefinition macro)
{
throw new NotImplementedException();
}
public string VisitNamespace(Namespace @namespace)
{
throw new NotImplementedException();
}
public string VisitEvent(Event @event)
{
throw new NotImplementedException();
}
public string VisitProperty(Property property)
{
throw new NotImplementedException();
}
public string ToString(Type type)
{
return type.Visit(this);
}
}
}

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

@ -2105,7 +2105,7 @@ namespace CppSharp.Generators.CSharp @@ -2105,7 +2105,7 @@ namespace CppSharp.Generators.CSharp
if (Driver.Options.MarshalCharAsManagedChar)
{
foreach (var param in method.Parameters.Where(
p => p.Type.Desugar().IsPrimitiveType(PrimitiveType.Int8)))
p => p.Type.IsPrimitiveType(PrimitiveType.Int8)))
{
WriteLine("if ({0} < char.MinValue || {0} > sbyte.MaxValue)", param.Name);
WriteLineIndent(
@ -2690,7 +2690,7 @@ namespace CppSharp.Generators.CSharp @@ -2690,7 +2690,7 @@ namespace CppSharp.Generators.CSharp
WriteLineIndent("EntryPoint=\"{0}\")]", function.Mangled);
if (function.ReturnType.Type.Desugar().IsPrimitiveType(PrimitiveType.Bool))
if (function.ReturnType.Type.IsPrimitiveType(PrimitiveType.Bool))
WriteLine("[return: MarshalAsAttribute(UnmanagedType.I1)]");
var @params = new List<string>();

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

@ -208,18 +208,27 @@ namespace CppSharp.Generators.CSharp @@ -208,18 +208,27 @@ namespace CppSharp.Generators.CSharp
if (IsConstCharString(pointer))
return isManagedContext ? "string" : "global::System.IntPtr";
PrimitiveType primitive;
var desugared = pointee.Desugar();
if (desugared.IsPrimitiveType(out primitive))
// From http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
// Any of the following types may be a pointer type:
// * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
// * Any enum type.
// * Any pointer type.
// * Any user-defined struct type that contains fields of unmanaged types only.
var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{
if (isManagedContext && Context.Parameter != null &&
(Context.Parameter.IsOut || Context.Parameter.IsInOut))
return VisitPrimitiveType(primitive, quals);
// Skip one indirection if passed by reference
var param = Context.Parameter;
if (isManagedContext && param != null && (param.IsOut || param.IsInOut)
&& pointee == finalPointee)
return pointee.Visit(this, quals);
if (ContextKind == CSharpTypePrinterContextKind.GenericDelegate)
return "global::System.IntPtr";
return VisitPrimitiveType(primitive, quals) + "*";
return pointee.Visit(this, quals) + "*";
}
Enumeration @enum;

2
src/Generator/Passes/CheckIgnoredDecls.cs

@ -342,7 +342,7 @@ namespace CppSharp.Passes @@ -342,7 +342,7 @@ namespace CppSharp.Passes
var arrayType = type as ArrayType;
PrimitiveType primitive;
if (arrayType != null && arrayType.SizeType == ArrayType.ArraySize.Constant &&
!arrayType.Type.Desugar().IsPrimitiveType(out primitive) &&
!arrayType.Type.IsPrimitiveType(out primitive) &&
!arrayType.Type.Desugar().IsPointerToPrimitiveType())
{
msg = "unsupported";

16
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -100,14 +100,18 @@ namespace CppSharp.Passes @@ -100,14 +100,18 @@ namespace CppSharp.Passes
if (!@operator.ReturnType.Qualifiers.IsConst && @operator.ReturnType.Type.IsAddress())
property.SetMethod = @operator;
// C++/CLI uses "default" as the indexer property name.
if (Driver.Options.IsCLIGenerator)
{
// If we've a setter use the pointee as the type of the property.
var pointerType = property.Type as PointerType;
if (pointerType != null && property.HasSetter)
{
property.QualifiedType = new QualifiedType(pointerType.Pointee, property.QualifiedType.Qualifiers);
property.GetMethod.ReturnType = property.QualifiedType;
}
// C++/CLI uses "default" as the indexer property name.
property.Name = "default";
property.GetMethod.Parameters[0].Name = "index";
if (property.SetMethod != null)
property.SetMethod.Parameters[0].Name = "index";
}
property.Parameters.AddRange(@operator.Parameters);

11
src/Generator/Types/Types.cs

@ -127,6 +127,17 @@ namespace CppSharp @@ -127,6 +127,17 @@ namespace CppSharp
Ignore();
return base.VisitTemplateSpecializationType(template, quals);
}
public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals)
{
// We don't know how to marshal non-static member functions
if (function.CallingConvention == CallingConvention.ThisCall)
{
Ignore();
return false;
}
return base.VisitFunctionType(function, quals);
}
}

24
tests/Basic/Basic.Tests.cs

@ -22,7 +22,17 @@ public class BasicTests : GeneratorTestFixture @@ -22,7 +22,17 @@ public class BasicTests : GeneratorTestFixture
Assert.That(hello.AddFoo(foo), Is.EqualTo(11));
Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11));
Assert.That(hello.AddFooPtr(foo), Is.EqualTo(11));
Assert.That(hello.AddFooRef(foo), Is.EqualTo(11));
Assert.That(hello.AddFooRef(foo), Is.EqualTo(11));
unsafe
{
var pointer = foo.SomePointer;
var pointerPointer = foo.SomePointerPointer;
for (int i = 0; i < 4; i++)
{
Assert.AreEqual(i, pointer[i]);
Assert.AreEqual(i, (*pointerPointer)[i]);
}
}
var bar = new Bar { A = 4, B = 7 };
Assert.That(hello.AddBar(bar), Is.EqualTo(11));
@ -166,6 +176,13 @@ public class BasicTests : GeneratorTestFixture @@ -166,6 +176,13 @@ public class BasicTests : GeneratorTestFixture
var delegates = new TestDelegates();
var doubleSum = delegates.A(2) + delegates.B(2);
Assert.AreEqual(8, doubleSum);
}
[Test]
public void TestAttributedDelegate()
{
var result = basic.AttributedDelegate(2);
Assert.AreEqual(4, result);
}
[Test]
@ -223,7 +240,10 @@ public class BasicTests : GeneratorTestFixture @@ -223,7 +240,10 @@ public class BasicTests : GeneratorTestFixture
public unsafe void TestIndexers()
{
var someStruct = new SomeStruct();
Assert.That(someStruct[0], Is.EqualTo(1));
Assert.That(someStruct[0], Is.EqualTo(1));
Assert.That(someStruct["foo"], Is.EqualTo(1));
someStruct[0] = 2;
Assert.That(someStruct[0], Is.EqualTo(2));
}
[Test]

5
tests/Basic/Basic.cpp

@ -2,6 +2,11 @@ @@ -2,6 +2,11 @@
Foo::Foo()
{
auto p = new int[4];
for (int i = 0; i < 4; i++)
p[i] = i;
SomePointer = p;
SomePointerPointer = &SomePointer;
}
const char* Foo::GetANSI()

27
tests/Basic/Basic.h

@ -18,7 +18,11 @@ public: @@ -18,7 +18,11 @@ public:
// TODO: VC++ does not support char16
// char16 chr16;
float nested_array[2][2];
// Not properly handled yet - ignore
float nested_array[2][2];
// Primitive pointer types
const int* SomePointer;
const int** SomePointerPointer;
};
struct DLL_API Bar
@ -243,14 +247,26 @@ typedef int (*DelegateInGlobalNamespace)(int); @@ -243,14 +247,26 @@ typedef int (*DelegateInGlobalNamespace)(int);
struct DLL_API TestDelegates
{
typedef int (*DelegateInClass)(int);
typedef int(TestDelegates::*MemberDelegate)(int);
TestDelegates() : A(Double), B(Double) {}
TestDelegates() : A(Double), B(Double) { C = &TestDelegates::Triple; }
static int Double(int N) { return N * 2; }
int Triple(int N) { return N * 3; }
DelegateInClass A;
DelegateInGlobalNamespace B;
// As long as we can't marshal them make sure they're ignored
MemberDelegate C;
};
// Tests delegate generation for attributed function types
typedef int(__cdecl *AttributedDelegate)(int n);
DLL_API int __cdecl Double(int n) { return n * 2; }
DLL_API AttributedDelegate GetAttributedDelegate()
{
return Double;
}
// Tests memory leaks in constructors
// C#: Marshal.FreeHGlobal(arg0);
struct DLL_API TestMemoryLeaks
@ -307,8 +323,9 @@ typedef unsigned long foo_t; @@ -307,8 +323,9 @@ typedef unsigned long foo_t;
typedef struct DLL_API SomeStruct
{
SomeStruct() : p(1) {}
const foo_t& operator[](int i) const { return p; }
foo_t operator[](int i) { return p; }
foo_t& operator[](int i) { return p; }
// CSharp backend can't deal with a setter here
foo_t operator[](const char* name) { return p; }
foo_t p;
}
SomeStruct;
@ -368,4 +385,4 @@ struct DLL_API TestGetterSetterToProperties @@ -368,4 +385,4 @@ struct DLL_API TestGetterSetterToProperties
{
int getWidth() { return 640; }
int getHeight() { return 480; }
};
};

Loading…
Cancel
Save