Browse Source

Generate valid C# for template indexers taking const char*

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1204/head
Dimitar Dobrev 6 years ago
parent
commit
9bc39c44ab
  1. 6
      src/AST/Type.cs
  2. 10
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  3. 8
      src/Generator/Generators/CSharp/CSharpSources.cs
  4. 2
      src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs
  5. 27
      src/Generator/Types/Std/Stdlib.cs
  6. 4
      tests/CSharp/CSharpTemplates.h

6
src/AST/Type.cs

@ -866,10 +866,12 @@ namespace CppSharp.AST
var type = obj as TemplateParameterSubstitutionType; var type = obj as TemplateParameterSubstitutionType;
if (type == null) return false; 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();
} }
/// <summary> /// <summary>

10
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -312,7 +312,8 @@ namespace CppSharp.Generators.CSharp
Type finalType = (returnType.GetFinalPointee() ?? returnType).Desugar(); Type finalType = (returnType.GetFinalPointee() ?? returnType).Desugar();
if (finalType.IsDependent) if (finalType.IsDependent)
Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) "); 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}) "); Context.Return.Write($"({typePrinter.IntPtrType}) ");
return base.VisitTemplateParameterSubstitutionType(param, quals); return base.VisitTemplateParameterSubstitutionType(param, quals);
} }
@ -623,9 +624,10 @@ namespace CppSharp.Generators.CSharp
public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals) public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals)
{ {
var replacement = param.Replacement.Type.Desugar(); var replacement = param.Replacement.Type.Desugar();
if (replacement.IsPrimitiveType() || if ((replacement.IsPrimitiveType() ||
replacement.IsPointerToPrimitiveType() || replacement.IsPointerToPrimitiveType() ||
replacement.IsEnum()) replacement.IsEnum()) &&
!replacement.IsConstCharString())
{ {
Context.Return.Write($"({replacement}) "); Context.Return.Write($"({replacement}) ");
if (replacement.IsPointerToPrimitiveType()) if (replacement.IsPointerToPrimitiveType())

8
src/Generator/Generators/CSharp/CSharpSources.cs

@ -1049,15 +1049,15 @@ namespace CppSharp.Generators.CSharp
if (type.IsPrimitiveType()) if (type.IsPrimitiveType())
{ {
WriteLine($@"*{@internal}.{internalFunction}({ WriteLine($@"*{@internal}.{internalFunction}({
GetInstanceParam(function)}, {(paramMarshal.Context == null ? GetInstanceParam(function)}, {paramMarshal.Context.ArgumentPrefix}{
paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};"); paramMarshal.Name}) = {marshal.Context.Return};");
} }
else else
{ {
var typeInternal = TypePrinter.PrintNative(type); var typeInternal = TypePrinter.PrintNative(type);
WriteLine($@"*({typeInternal}*) {@internal}.{internalFunction}({ WriteLine($@"*({typeInternal}*) {@internal}.{internalFunction}({
GetInstanceParam(function)}, {(paramMarshal.Context == null ? GetInstanceParam(function)}, {paramMarshal.Context.ArgumentPrefix}{
paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};"); paramMarshal.Name}) = {marshal.Context.Return};");
} }
} }

2
src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs

@ -139,7 +139,7 @@ namespace CppSharp.Generators.CSharp
i => i =>
{ {
CppSharp.AST.Type type = specialization.Arguments[i].Type.Type; 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}.FullName == \"System.IntPtr\"" :
$"__{@class.TemplateParameters[i].Name}.IsAssignableFrom(typeof({type}))"; $"__{@class.TemplateParameters[i].Name}.IsAssignableFrom(typeof({type}))";
}))); })));

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

@ -167,24 +167,31 @@ namespace CppSharp.Types.Std
public override void CSharpMarshalToNative(CSharpMarshalContext ctx) public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
{ {
string param = ctx.Parameter.Name;
if (ctx.Parameter.Usage == ParameterUsage.Unknown && if (ctx.Parameter.Usage == ParameterUsage.Unknown &&
!ctx.Parameter.Type.IsReference() && !ctx.Parameter.Type.IsReference() &&
!(ctx.Parameter.Type is TemplateParameterSubstitutionType) &&
ctx.MarshalKind != MarshalKind.NativeField && ctx.MarshalKind != MarshalKind.NativeField &&
ctx.MarshalKind != MarshalKind.VTableReturnValue && ctx.MarshalKind != MarshalKind.VTableReturnValue &&
ctx.MarshalKind != MarshalKind.Variable) ctx.MarshalKind != MarshalKind.Variable)
{ {
ctx.Return.Write(ctx.Parameter.Name); ctx.Return.Write(param);
return; return;
} }
var substitution = Type as TemplateParameterSubstitutionType;
if (substitution != null)
param = $"({substitution.Replacement}) (object) {param}";
if (Equals(Context.Options.Encoding, Encoding.ASCII)) if (Equals(Context.Options.Encoding, Encoding.ASCII))
{ {
ctx.Return.Write($"Marshal.StringToHGlobalAnsi({ctx.Parameter.Name})"); ctx.Return.Write($"Marshal.StringToHGlobalAnsi({param})");
return; return;
} }
if (Equals(Context.Options.Encoding, Encoding.Unicode) || if (Equals(Context.Options.Encoding, Encoding.Unicode) ||
Equals(Context.Options.Encoding, Encoding.BigEndianUnicode)) Equals(Context.Options.Encoding, Encoding.BigEndianUnicode))
{ {
ctx.Return.Write($"Marshal.StringToHGlobalUni({ctx.Parameter.Name})"); ctx.Return.Write($"Marshal.StringToHGlobalUni({param})");
return; return;
} }
throw new System.NotSupportedException( throw new System.NotSupportedException(
@ -200,7 +207,7 @@ namespace CppSharp.Types.Std
return; return;
} }
Type type = ctx.ReturnType.Type.Desugar(); Type type = Type.Desugar();
Type pointee = type.GetPointee().Desugar(); Type pointee = type.GetPointee().Desugar();
var isChar = type.IsPointerToPrimitiveType(PrimitiveType.Char) || var isChar = type.IsPointerToPrimitiveType(PrimitiveType.Char) ||
(pointee.IsPointerToPrimitiveType(PrimitiveType.Char) && (pointee.IsPointerToPrimitiveType(PrimitiveType.Char) &&
@ -211,27 +218,31 @@ namespace CppSharp.Types.Std
if (Equals(encoding, Encoding.ASCII)) if (Equals(encoding, Encoding.ASCII))
encoding = Context.Options.Encoding; 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)) if (Equals(encoding, Encoding.ASCII))
{ {
ctx.Return.Write($"Marshal.PtrToStringAnsi({ctx.ReturnVarName})"); ctx.Return.Write($"Marshal.PtrToStringAnsi({returnVarName})");
return; return;
} }
if (Equals(encoding, Encoding.UTF8)) if (Equals(encoding, Encoding.UTF8))
{ {
ctx.Return.Write($"Marshal.PtrToStringUTF8({ctx.ReturnVarName})"); ctx.Return.Write($"Marshal.PtrToStringUTF8({returnVarName})");
return; return;
} }
// If we reach this, we know the string is Unicode. // If we reach this, we know the string is Unicode.
if (isChar || ctx.Context.TargetInfo.WCharWidth == 16) if (isChar || ctx.Context.TargetInfo.WCharWidth == 16)
{ {
ctx.Return.Write($"Marshal.PtrToStringUni({ctx.ReturnVarName})"); ctx.Return.Write($"Marshal.PtrToStringUni({returnVarName})");
return; return;
} }
// If we reach this, we should have an UTF-32 wide string. // If we reach this, we should have an UTF-32 wide string.
const string encodingName = "System.Text.Encoding.UTF32"; const string encodingName = "System.Text.Encoding.UTF32";
ctx.Return.Write($@"CppSharp.Runtime.Helpers.MarshalEncodedString({ ctx.Return.Write($@"CppSharp.Runtime.Helpers.MarshalEncodedString({
ctx.ReturnVarName}, {encodingName})"); returnVarName}, {encodingName})");
} }
} }

4
tests/CSharp/CSharpTemplates.h

@ -715,7 +715,8 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
TemplateDerivedFromRegularDynamic<RegularDynamic> _14, TemplateDerivedFromRegularDynamic<RegularDynamic> _14,
IndependentFields<OnlySpecialisedInTypeArg<double>> _15, IndependentFields<OnlySpecialisedInTypeArg<double>> _15,
DependentPointerFields<float> _16, IndependentFields<const T1&> _17, DependentPointerFields<float> _16, IndependentFields<const T1&> _17,
TemplateWithIndexer<T2*> _18, IndependentFields<int(*)(int)>, std::string s); TemplateWithIndexer<T2*> _18, IndependentFields<int(*)(int)> _19,
TemplateWithIndexer<const char*> _20, std::string s);
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii); void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii);
@ -750,6 +751,7 @@ template class DLL_API TemplateWithIndexer<UsedInTemplatedIndexer>;
template class DLL_API TemplateWithIndexer<T1>; template class DLL_API TemplateWithIndexer<T1>;
template class DLL_API TemplateWithIndexer<T2*>; template class DLL_API TemplateWithIndexer<T2*>;
template class DLL_API TemplateWithIndexer<float>; template class DLL_API TemplateWithIndexer<float>;
template class DLL_API TemplateWithIndexer<const char*>;
template class DLL_API TemplateDerivedFromRegularDynamic<RegularDynamic>; template class DLL_API TemplateDerivedFromRegularDynamic<RegularDynamic>;
template class DLL_API HasCtorWithMappedToEnum<TestFlag>; template class DLL_API HasCtorWithMappedToEnum<TestFlag>;

Loading…
Cancel
Save