Skip to content

Commit 9bc39c4

Browse files
committed
Generate valid C# for template indexers taking const char*
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent 3caa8c5 commit 9bc39c4

File tree

6 files changed

+37
-20
lines changed

6 files changed

+37
-20
lines changed

src/AST/Type.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -866,10 +866,12 @@ public override bool Equals(object obj)
866866
var type = obj as TemplateParameterSubstitutionType;
867867
if (type == null) return false;
868868

869-
return Replacement.Equals(type.Replacement);
869+
return ReplacedParameter.Equals(type.ReplacedParameter) &&
870+
Replacement.Equals(type.Replacement);
870871
}
871872

872-
public override int GetHashCode() => Replacement.GetHashCode();
873+
public override int GetHashCode() =>
874+
ReplacedParameter.GetHashCode() ^ Replacement.GetHashCode();
873875
}
874876

875877
/// <summary>

src/Generator/Generators/CSharp/CSharpMarshal.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@ public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSub
312312
Type finalType = (returnType.GetFinalPointee() ?? returnType).Desugar();
313313
if (finalType.IsDependent)
314314
Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) ");
315-
if (param.Replacement.Type.Desugar().IsPointerToPrimitiveType())
315+
Type replacement = param.Replacement.Type.Desugar();
316+
if (replacement.IsPointerToPrimitiveType() && !replacement.IsConstCharString())
316317
Context.Return.Write($"({typePrinter.IntPtrType}) ");
317318
return base.VisitTemplateParameterSubstitutionType(param, quals);
318319
}
@@ -623,9 +624,10 @@ public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
623624
public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals)
624625
{
625626
var replacement = param.Replacement.Type.Desugar();
626-
if (replacement.IsPrimitiveType() ||
627-
replacement.IsPointerToPrimitiveType() ||
628-
replacement.IsEnum())
627+
if ((replacement.IsPrimitiveType() ||
628+
replacement.IsPointerToPrimitiveType() ||
629+
replacement.IsEnum()) &&
630+
!replacement.IsConstCharString())
629631
{
630632
Context.Return.Write($"({replacement}) ");
631633
if (replacement.IsPointerToPrimitiveType())

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,15 +1049,15 @@ private void GenerateIndexerSetter(Function function)
10491049
if (type.IsPrimitiveType())
10501050
{
10511051
WriteLine($@"*{@internal}.{internalFunction}({
1052-
GetInstanceParam(function)}, {(paramMarshal.Context == null ?
1053-
paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};");
1052+
GetInstanceParam(function)}, {paramMarshal.Context.ArgumentPrefix}{
1053+
paramMarshal.Name}) = {marshal.Context.Return};");
10541054
}
10551055
else
10561056
{
10571057
var typeInternal = TypePrinter.PrintNative(type);
10581058
WriteLine($@"*({typeInternal}*) {@internal}.{internalFunction}({
1059-
GetInstanceParam(function)}, {(paramMarshal.Context == null ?
1060-
paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};");
1059+
GetInstanceParam(function)}, {paramMarshal.Context.ArgumentPrefix}{
1060+
paramMarshal.Name}) = {marshal.Context.Return};");
10611061
}
10621062
}
10631063

src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private static void WriteTemplateSpecializationCheck(CSharpSources gen,
139139
i =>
140140
{
141141
CppSharp.AST.Type type = specialization.Arguments[i].Type.Type;
142-
return type.IsPointerToPrimitiveType() ?
142+
return type.IsPointerToPrimitiveType() && !type.IsConstCharString() ?
143143
$"__{@class.TemplateParameters[i].Name}.FullName == \"System.IntPtr\"" :
144144
$"__{@class.TemplateParameters[i].Name}.IsAssignableFrom(typeof({type}))";
145145
})));

src/Generator/Types/Std/Stdlib.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,24 +167,31 @@ public override Type CSharpSignatureType(TypePrinterContext ctx)
167167

168168
public override void CSharpMarshalToNative(CSharpMarshalContext ctx)
169169
{
170+
string param = ctx.Parameter.Name;
170171
if (ctx.Parameter.Usage == ParameterUsage.Unknown &&
171172
!ctx.Parameter.Type.IsReference() &&
173+
!(ctx.Parameter.Type is TemplateParameterSubstitutionType) &&
172174
ctx.MarshalKind != MarshalKind.NativeField &&
173175
ctx.MarshalKind != MarshalKind.VTableReturnValue &&
174176
ctx.MarshalKind != MarshalKind.Variable)
175177
{
176-
ctx.Return.Write(ctx.Parameter.Name);
178+
ctx.Return.Write(param);
177179
return;
178180
}
181+
182+
var substitution = Type as TemplateParameterSubstitutionType;
183+
if (substitution != null)
184+
param = $"({substitution.Replacement}) (object) {param}";
185+
179186
if (Equals(Context.Options.Encoding, Encoding.ASCII))
180187
{
181-
ctx.Return.Write($"Marshal.StringToHGlobalAnsi({ctx.Parameter.Name})");
188+
ctx.Return.Write($"Marshal.StringToHGlobalAnsi({param})");
182189
return;
183190
}
184191
if (Equals(Context.Options.Encoding, Encoding.Unicode) ||
185192
Equals(Context.Options.Encoding, Encoding.BigEndianUnicode))
186193
{
187-
ctx.Return.Write($"Marshal.StringToHGlobalUni({ctx.Parameter.Name})");
194+
ctx.Return.Write($"Marshal.StringToHGlobalUni({param})");
188195
return;
189196
}
190197
throw new System.NotSupportedException(
@@ -200,7 +207,7 @@ public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
200207
return;
201208
}
202209

203-
Type type = ctx.ReturnType.Type.Desugar();
210+
Type type = Type.Desugar();
204211
Type pointee = type.GetPointee().Desugar();
205212
var isChar = type.IsPointerToPrimitiveType(PrimitiveType.Char) ||
206213
(pointee.IsPointerToPrimitiveType(PrimitiveType.Char) &&
@@ -211,27 +218,31 @@ public override void CSharpMarshalToManaged(CSharpMarshalContext ctx)
211218
if (Equals(encoding, Encoding.ASCII))
212219
encoding = Context.Options.Encoding;
213220

221+
string returnVarName = ctx.Function != null &&
222+
ctx.Function.ReturnType.Type.Desugar().IsAddress() ?
223+
$"(global::System.IntPtr) {ctx.ReturnVarName}" : ctx.ReturnVarName;
224+
214225
if (Equals(encoding, Encoding.ASCII))
215226
{
216-
ctx.Return.Write($"Marshal.PtrToStringAnsi({ctx.ReturnVarName})");
227+
ctx.Return.Write($"Marshal.PtrToStringAnsi({returnVarName})");
217228
return;
218229
}
219230
if (Equals(encoding, Encoding.UTF8))
220231
{
221-
ctx.Return.Write($"Marshal.PtrToStringUTF8({ctx.ReturnVarName})");
232+
ctx.Return.Write($"Marshal.PtrToStringUTF8({returnVarName})");
222233
return;
223234
}
224235

225236
// If we reach this, we know the string is Unicode.
226237
if (isChar || ctx.Context.TargetInfo.WCharWidth == 16)
227238
{
228-
ctx.Return.Write($"Marshal.PtrToStringUni({ctx.ReturnVarName})");
239+
ctx.Return.Write($"Marshal.PtrToStringUni({returnVarName})");
229240
return;
230241
}
231242
// If we reach this, we should have an UTF-32 wide string.
232243
const string encodingName = "System.Text.Encoding.UTF32";
233244
ctx.Return.Write($@"CppSharp.Runtime.Helpers.MarshalEncodedString({
234-
ctx.ReturnVarName}, {encodingName})");
245+
returnVarName}, {encodingName})");
235246
}
236247
}
237248

tests/CSharp/CSharpTemplates.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,8 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
715715
TemplateDerivedFromRegularDynamic<RegularDynamic> _14,
716716
IndependentFields<OnlySpecialisedInTypeArg<double>> _15,
717717
DependentPointerFields<float> _16, IndependentFields<const T1&> _17,
718-
TemplateWithIndexer<T2*> _18, IndependentFields<int(*)(int)>, std::string s);
718+
TemplateWithIndexer<T2*> _18, IndependentFields<int(*)(int)> _19,
719+
TemplateWithIndexer<const char*> _20, std::string s);
719720

720721
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii);
721722

@@ -750,6 +751,7 @@ template class DLL_API TemplateWithIndexer<UsedInTemplatedIndexer>;
750751
template class DLL_API TemplateWithIndexer<T1>;
751752
template class DLL_API TemplateWithIndexer<T2*>;
752753
template class DLL_API TemplateWithIndexer<float>;
754+
template class DLL_API TemplateWithIndexer<const char*>;
753755
template class DLL_API TemplateDerivedFromRegularDynamic<RegularDynamic>;
754756
template class DLL_API HasCtorWithMappedToEnum<TestFlag>;
755757

0 commit comments

Comments
 (0)