From 0cfc06001812a98d3149399649f8beec02f14303 Mon Sep 17 00:00:00 2001 From: josetr <37419832+josetr@users.noreply.github.com> Date: Fri, 23 Oct 2020 19:41:08 +0100 Subject: [PATCH] Fix string marshalling bug and move hard to read code to CppSharp.Runtime (#1445) --- src/Generator/Types/Std/Stdlib.cs | 47 ++----------------------------- src/Runtime/MarshalUtil.cs | 34 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 44 deletions(-) create mode 100644 src/Runtime/MarshalUtil.cs diff --git a/src/Generator/Types/Std/Stdlib.cs b/src/Generator/Types/Std/Stdlib.cs index c78c02b9..a51a8a62 100644 --- a/src/Generator/Types/Std/Stdlib.cs +++ b/src/Generator/Types/Std/Stdlib.cs @@ -242,45 +242,18 @@ namespace CppSharp.Types.Std } string returnVarName = ctx.ReturnVarName; - string nullPtr = "global::System.IntPtr.Zero"; if (ctx.Function != null) { Type returnType = ctx.Function.ReturnType.Type.Desugar(); if (returnType.IsAddress() && returnType.GetPointee().Desugar().IsAddress()) { - returnVarName = $"*{returnVarName}"; - nullPtr = "null"; + returnVarName = $"new global::System.IntPtr(*{returnVarName})"; } } - TextGenerator textGenerator; - if (ctx.Parameter == null) - { - textGenerator = ctx.Before; - textGenerator.WriteLine($"if ({ctx.ReturnVarName} == {nullPtr})"); - textGenerator.WriteLineIndent($"return default({ctx.ReturnType});"); - } - else - { - textGenerator = ctx.Cleanup; - textGenerator.WriteLine($"if ({ctx.ReturnVarName} == {nullPtr})"); - textGenerator.WriteOpenBraceAndIndent(); - textGenerator.WriteLine($"{ctx.Parameter.Name} = default({Type.Desugar()});"); - textGenerator.WriteLine($"return{(ctx.Function.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void) ? "" : " default")};"); - textGenerator.UnindentAndWriteCloseBrace(); - } - - string encoding = GetEncoding().Name; - string type = GetTypeForCodePoint(encoding); - var retPtr = Generator.GeneratedIdentifier($"retPtr{ctx.ParameterIndex}"); - var length = Generator.GeneratedIdentifier($"length{ctx.ParameterIndex}"); - textGenerator.WriteLine($"var {retPtr} = ({type}*) {returnVarName};"); - textGenerator.WriteLine($"int {length} = 0;"); - textGenerator.WriteLine($"while (*({retPtr}++) != 0) {length} += sizeof({type});"); - - ctx.Return.Write($@"global::System.Text.Encoding.{ - encoding}.GetString((byte*) {returnVarName}, {length})"); + var encoding = $"global::System.Text.Encoding.{GetEncoding().Name}"; + ctx.Return.Write($@"CppSharp.Runtime.MarshalUtil.GetString({encoding}, {returnVarName})"); } private (Encoding Encoding, string Name) GetEncoding() @@ -310,20 +283,6 @@ namespace CppSharp.Types.Std throw new System.NotSupportedException( $"{Context.Options.Encoding.EncodingName} is not supported yet."); } - - private static string GetTypeForCodePoint(string encoding) - { - switch (encoding) - { - case nameof(Encoding.UTF32): - return "int"; - case nameof(Encoding.Unicode): - case nameof(Encoding.BigEndianUnicode): - return "short"; - default: - return "byte"; - } - } } [TypeMap("const char[]", GeneratorKind = GeneratorKind.CSharp)] diff --git a/src/Runtime/MarshalUtil.cs b/src/Runtime/MarshalUtil.cs new file mode 100644 index 00000000..ea880d2f --- /dev/null +++ b/src/Runtime/MarshalUtil.cs @@ -0,0 +1,34 @@ +using System; +using System.Text; + +namespace CppSharp.Runtime +{ + public unsafe static class MarshalUtil + { + public static string GetString(Encoding encoding, IntPtr str) + { + if (str == IntPtr.Zero) + return null; + + int byteCount = 0; + + if (encoding == Encoding.UTF32) + { + var str32 = (int*)str; + while (*(str32++) != 0) byteCount += sizeof(int); + } + else if (encoding == Encoding.Unicode || encoding == Encoding.BigEndianUnicode) + { + var str16 = (short*)str; + while (*(str16++) != 0) byteCount += sizeof(short); + } + else + { + var str8 = (byte*)str; + while (*(str8++) != 0) byteCount += sizeof(byte); + } + + return encoding.GetString((byte*)str, byteCount); + } + } +}