From c281f57b5288ac3a3d03c2448505f356f07bdc76 Mon Sep 17 00:00:00 2001 From: Ahmed Elsayed Date: Wed, 23 Feb 2022 18:15:55 +0200 Subject: [PATCH] Add Experimental Initial Span (#1651) * Fix NotImplementedException * Add Experimental Span * Fix Some Problems and Comment --- .../Generators/CSharp/CSharpMarshal.cs | 49 +++++++++++++++---- .../Generators/CSharp/CSharpTypePrinter.cs | 14 ++++++ src/Generator/Options.cs | 6 +++ 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 09d2135e..7c843f9f 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -69,11 +69,19 @@ namespace CppSharp.Generators.CSharp var arrayType = array.Type.Desugar(); if (CheckIfArrayCanBeCopiedUsingMemoryCopy(array)) - Context.Return.Write($"CppSharp.Runtime.MarshalUtil.GetArray<{arrayType}>({Context.ReturnVarName}, {array.Size})"); + { + if (Context.Context.Options.UseSpan) + Context.Return.Write($"new Span<{arrayType}>({Context.ReturnVarName}, {array.Size})"); + else + Context.Return.Write($"CppSharp.Runtime.MarshalUtil.GetArray<{arrayType}>({Context.ReturnVarName}, {array.Size})"); + } else if (array.Type.IsPrimitiveType(PrimitiveType.Char) && Context.Context.Options.MarshalCharAsManagedChar) Context.Return.Write($"CppSharp.Runtime.MarshalUtil.GetCharArray({Context.ReturnVarName}, {array.Size})"); else if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void)) - Context.Return.Write($"CppSharp.Runtime.MarshalUtil.GetIntPtrArray({Context.ReturnVarName}, {array.Size})"); + if (Context.Context.Options.UseSpan) + Context.Return.Write($"Span({Context.ReturnVarName}, {array.Size})"); + else + Context.Return.Write($"CppSharp.Runtime.MarshalUtil.GetIntPtrArray({Context.ReturnVarName}, {array.Size})"); else { string value = Generator.GeneratedIdentifier("value"); @@ -876,17 +884,29 @@ namespace CppSharp.Generators.CSharp if (elementType.IsPrimitiveType() || elementType.IsPointerToPrimitiveType()) { - Context.Return.Write(Context.Parameter.Name); + if (Context.Context.Options.UseSpan && !elementType.IsConstCharString()) + { + var local = Generator.GeneratedIdentifier($@"{ + Context.Parameter.Name}{Context.ParameterIndex}"); + Context.Before.WriteLine($@"fixed ({ + typePrinter.PrintNative(elementType)}* {local} = &MemoryMarshal.GetReference({Context.Parameter.Name}))"); + Context.HasCodeBlock = true; + Context.Before.WriteOpenBraceAndIndent(); + Context.Return.Write(local); + } + else + Context.Return.Write(Context.Parameter.Name); return; } var intermediateArray = Generator.GeneratedIdentifier(Context.Parameter.Name); var intermediateArrayType = typePrinter.PrintNative(elementType); - - Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); - - Context.Before.WriteLine($"if ({Context.Parameter.Name} is null)"); - Context.Before.WriteLineIndent($"{intermediateArray} = null;"); + if (Context.Context.Options.UseSpan) + Context.Before.WriteLine($"Span<{intermediateArrayType}> {intermediateArray};"); + else + Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); + Context.Before.WriteLine($"if ({Context.Parameter.Name} == null)"); + Context.Before.WriteLineIndent($"{intermediateArray} = null;"); Context.Before.WriteLine("else"); Context.Before.WriteOpenBraceAndIndent(); @@ -911,7 +931,18 @@ namespace CppSharp.Generators.CSharp Context.Before.UnindentAndWriteCloseBrace(); - Context.Return.Write(intermediateArray); + if (Context.Context.Options.UseSpan) + { + var local = Generator.GeneratedIdentifier($@"{ + intermediateArray}{Context.ParameterIndex}"); + Context.Before.WriteLine($@"fixed ({ + typePrinter.PrintNative(elementType)}* {local} = &MemoryMarshal.GetReference({intermediateArray}))"); + Context.HasCodeBlock = true; + Context.Before.WriteOpenBraceAndIndent(); + Context.Return.Write(local); + } + else + Context.Return.Write(intermediateArray); } private void MarshalString(Type pointee) diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 94043f96..9e09467d 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -123,6 +123,20 @@ namespace CppSharp.Generators.CSharp return $"{prefix}string[]"; } + if (Context.Options.UseSpan && !(array.SizeType != ArrayType.ArraySize.Constant && + MarshalKind == MarshalKind.ReturnVariableArray)) + { + if (ContextKind == TypePrinterContextKind.Managed) + { + return $"Span<{arrayType.Visit(this)}>"; + } + else + { + return $"{arrayType.Visit(this)}*"; ; + + } + } + var arraySuffix = array.SizeType != ArrayType.ArraySize.Constant && MarshalKind == MarshalKind.ReturnVariableArray ? (ContextKind == TypePrinterContextKind.Managed && diff --git a/src/Generator/Options.cs b/src/Generator/Options.cs index 4ce91c85..b7370ed4 100644 --- a/src/Generator/Options.cs +++ b/src/Generator/Options.cs @@ -184,6 +184,12 @@ namespace CppSharp public readonly List DependentNameSpaces = new List(); public bool MarshalCharAsManagedChar { get; set; } + /// + /// Use Span Struct instead of Managed Array + /// + public bool UseSpan { get; set; } + + /// /// Generates a single C# file. ///