From 9bc39c44abd049d5afa85b154de610338920c4ee Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sat, 13 Apr 2019 06:18:19 +0300 Subject: [PATCH] Generate valid C# for template indexers taking const char* Signed-off-by: Dimitar Dobrev --- src/AST/Type.cs | 6 +++-- .../Generators/CSharp/CSharpMarshal.cs | 10 ++++--- .../Generators/CSharp/CSharpSources.cs | 8 +++--- .../CSharp/CSharpSourcesExtensions.cs | 2 +- src/Generator/Types/Std/Stdlib.cs | 27 +++++++++++++------ tests/CSharp/CSharpTemplates.h | 4 ++- 6 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/AST/Type.cs b/src/AST/Type.cs index b3cf9d8c..311c9ec5 100644 --- a/src/AST/Type.cs +++ b/src/AST/Type.cs @@ -866,10 +866,12 @@ namespace CppSharp.AST var type = obj as TemplateParameterSubstitutionType; if (type == null) return false; - return Replacement.Equals(type.Replacement); + return ReplacedParameter.Equals(type.ReplacedParameter) && + Replacement.Equals(type.Replacement); } - public override int GetHashCode() => Replacement.GetHashCode(); + public override int GetHashCode() => + ReplacedParameter.GetHashCode() ^ Replacement.GetHashCode(); } /// diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index ceda0fb6..c567e514 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -312,7 +312,8 @@ namespace CppSharp.Generators.CSharp Type finalType = (returnType.GetFinalPointee() ?? returnType).Desugar(); if (finalType.IsDependent) Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) "); - if (param.Replacement.Type.Desugar().IsPointerToPrimitiveType()) + Type replacement = param.Replacement.Type.Desugar(); + if (replacement.IsPointerToPrimitiveType() && !replacement.IsConstCharString()) Context.Return.Write($"({typePrinter.IntPtrType}) "); return base.VisitTemplateParameterSubstitutionType(param, quals); } @@ -623,9 +624,10 @@ namespace CppSharp.Generators.CSharp public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals) { var replacement = param.Replacement.Type.Desugar(); - if (replacement.IsPrimitiveType() || - replacement.IsPointerToPrimitiveType() || - replacement.IsEnum()) + if ((replacement.IsPrimitiveType() || + replacement.IsPointerToPrimitiveType() || + replacement.IsEnum()) && + !replacement.IsConstCharString()) { Context.Return.Write($"({replacement}) "); if (replacement.IsPointerToPrimitiveType()) diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index d0827499..296e07eb 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -1049,15 +1049,15 @@ namespace CppSharp.Generators.CSharp if (type.IsPrimitiveType()) { WriteLine($@"*{@internal}.{internalFunction}({ - GetInstanceParam(function)}, {(paramMarshal.Context == null ? - paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};"); + GetInstanceParam(function)}, {paramMarshal.Context.ArgumentPrefix}{ + paramMarshal.Name}) = {marshal.Context.Return};"); } else { var typeInternal = TypePrinter.PrintNative(type); WriteLine($@"*({typeInternal}*) {@internal}.{internalFunction}({ - GetInstanceParam(function)}, {(paramMarshal.Context == null ? - paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};"); + GetInstanceParam(function)}, {paramMarshal.Context.ArgumentPrefix}{ + paramMarshal.Name}) = {marshal.Context.Return};"); } } diff --git a/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs b/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs index fb337a41..03e13ada 100644 --- a/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs +++ b/src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs @@ -139,7 +139,7 @@ namespace CppSharp.Generators.CSharp i => { CppSharp.AST.Type type = specialization.Arguments[i].Type.Type; - return type.IsPointerToPrimitiveType() ? + return type.IsPointerToPrimitiveType() && !type.IsConstCharString() ? $"__{@class.TemplateParameters[i].Name}.FullName == \"System.IntPtr\"" : $"__{@class.TemplateParameters[i].Name}.IsAssignableFrom(typeof({type}))"; }))); diff --git a/src/Generator/Types/Std/Stdlib.cs b/src/Generator/Types/Std/Stdlib.cs index b7715f21..71e9de4f 100644 --- a/src/Generator/Types/Std/Stdlib.cs +++ b/src/Generator/Types/Std/Stdlib.cs @@ -167,24 +167,31 @@ namespace CppSharp.Types.Std public override void CSharpMarshalToNative(CSharpMarshalContext ctx) { + string param = ctx.Parameter.Name; if (ctx.Parameter.Usage == ParameterUsage.Unknown && !ctx.Parameter.Type.IsReference() && + !(ctx.Parameter.Type is TemplateParameterSubstitutionType) && ctx.MarshalKind != MarshalKind.NativeField && ctx.MarshalKind != MarshalKind.VTableReturnValue && ctx.MarshalKind != MarshalKind.Variable) { - ctx.Return.Write(ctx.Parameter.Name); + ctx.Return.Write(param); return; } + + var substitution = Type as TemplateParameterSubstitutionType; + if (substitution != null) + param = $"({substitution.Replacement}) (object) {param}"; + if (Equals(Context.Options.Encoding, Encoding.ASCII)) { - ctx.Return.Write($"Marshal.StringToHGlobalAnsi({ctx.Parameter.Name})"); + ctx.Return.Write($"Marshal.StringToHGlobalAnsi({param})"); return; } if (Equals(Context.Options.Encoding, Encoding.Unicode) || Equals(Context.Options.Encoding, Encoding.BigEndianUnicode)) { - ctx.Return.Write($"Marshal.StringToHGlobalUni({ctx.Parameter.Name})"); + ctx.Return.Write($"Marshal.StringToHGlobalUni({param})"); return; } throw new System.NotSupportedException( @@ -200,7 +207,7 @@ namespace CppSharp.Types.Std return; } - Type type = ctx.ReturnType.Type.Desugar(); + Type type = Type.Desugar(); Type pointee = type.GetPointee().Desugar(); var isChar = type.IsPointerToPrimitiveType(PrimitiveType.Char) || (pointee.IsPointerToPrimitiveType(PrimitiveType.Char) && @@ -211,27 +218,31 @@ namespace CppSharp.Types.Std if (Equals(encoding, Encoding.ASCII)) encoding = Context.Options.Encoding; + string returnVarName = ctx.Function != null && + ctx.Function.ReturnType.Type.Desugar().IsAddress() ? + $"(global::System.IntPtr) {ctx.ReturnVarName}" : ctx.ReturnVarName; + if (Equals(encoding, Encoding.ASCII)) { - ctx.Return.Write($"Marshal.PtrToStringAnsi({ctx.ReturnVarName})"); + ctx.Return.Write($"Marshal.PtrToStringAnsi({returnVarName})"); return; } if (Equals(encoding, Encoding.UTF8)) { - ctx.Return.Write($"Marshal.PtrToStringUTF8({ctx.ReturnVarName})"); + ctx.Return.Write($"Marshal.PtrToStringUTF8({returnVarName})"); return; } // If we reach this, we know the string is Unicode. if (isChar || ctx.Context.TargetInfo.WCharWidth == 16) { - ctx.Return.Write($"Marshal.PtrToStringUni({ctx.ReturnVarName})"); + ctx.Return.Write($"Marshal.PtrToStringUni({returnVarName})"); return; } // If we reach this, we should have an UTF-32 wide string. const string encodingName = "System.Text.Encoding.UTF32"; ctx.Return.Write($@"CppSharp.Runtime.Helpers.MarshalEncodedString({ - ctx.ReturnVarName}, {encodingName})"); + returnVarName}, {encodingName})"); } } diff --git a/tests/CSharp/CSharpTemplates.h b/tests/CSharp/CSharpTemplates.h index b79eb0aa..b7296e72 100644 --- a/tests/CSharp/CSharpTemplates.h +++ b/tests/CSharp/CSharpTemplates.h @@ -715,7 +715,8 @@ void forceUseSpecializations(IndependentFields _1, IndependentFields TemplateDerivedFromRegularDynamic _14, IndependentFields> _15, DependentPointerFields _16, IndependentFields _17, - TemplateWithIndexer _18, IndependentFields, std::string s); + TemplateWithIndexer _18, IndependentFields _19, + TemplateWithIndexer _20, std::string s); void hasIgnoredParam(DependentValueFields> ii); @@ -750,6 +751,7 @@ template class DLL_API TemplateWithIndexer; template class DLL_API TemplateWithIndexer; template class DLL_API TemplateWithIndexer; template class DLL_API TemplateWithIndexer; +template class DLL_API TemplateWithIndexer; template class DLL_API TemplateDerivedFromRegularDynamic; template class DLL_API HasCtorWithMappedToEnum;