From f6033f3a5ac7100176c6366a08d56e3907c6c6e2 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Tue, 12 Sep 2017 21:40:57 +0300 Subject: [PATCH] Fixed the generated C# for virtuals taking arrays of objects. Signed-off-by: Dimitar Dobrev --- .../Generators/CSharp/CSharpMarshal.cs | 54 +++++++++++++++++-- tests/CSharp/CSharp.Tests.cs | 12 +++++ tests/CSharp/CSharp.cpp | 47 ++++++++-------- tests/CSharp/CSharp.h | 14 ++--- 4 files changed, 93 insertions(+), 34 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 7f4f0032..c570c60c 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -128,8 +128,8 @@ namespace CppSharp.Generators.CSharp { QualifiedPointee = array.QualifiedType }, quals); - - goto case ArrayType.ArraySize.Variable; + MarshalVariableArray(array); + break; case ArrayType.ArraySize.Variable: Context.Return.Write(Context.ReturnVarName); break; @@ -384,6 +384,52 @@ namespace CppSharp.Generators.CSharp return ret; } + private void MarshalVariableArray(ArrayType array) + { + Type arrayType = array.Type.Desugar(); + if (arrayType.IsPrimitiveType() || + arrayType.IsPointerToPrimitiveType(PrimitiveType.Char) || + Context.MarshalKind != MarshalKind.GenericDelegate) + { + Context.Return.Write(Context.ReturnVarName); + return; + } + + var intermediateArray = Generator.GeneratedIdentifier(Context.ReturnVarName); + var intermediateArrayType = arrayType.Visit(typePrinter); + + Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); + + Context.Before.WriteLine($"if (ReferenceEquals({Context.ReturnVarName}, null))"); + Context.Before.WriteLineIndent($"{intermediateArray} = null;"); + Context.Before.WriteLine("else"); + + Context.Before.WriteStartBraceIndent(); + Context.Before.WriteLine($@"{intermediateArray} = new { + intermediateArrayType}[{Context.ReturnVarName}.Length];"); + Context.Before.WriteLine($"for (int i = 0; i < {intermediateArray}.Length; i++)"); + + if (arrayType.IsAddress()) + { + Context.Before.WriteStartBraceIndent(); + string element = Generator.GeneratedIdentifier("element"); + Context.Before.WriteLine($"var {element} = {Context.ReturnVarName}[i];"); + var intPtrZero = $"{CSharpTypePrinter.IntPtrType}.Zero"; + Context.Before.WriteLine($@"{intermediateArray}[i] = {element} == { + intPtrZero} ? null : {intermediateArrayType}.{ + Helpers.CreateInstanceIdentifier}({element});"); + Context.Before.WriteCloseBraceIndent(); + } + else + Context.Before.WriteLineIndent($@"{intermediateArray}[i] = { + intermediateArrayType}.{Helpers.CreateInstanceIdentifier}({ + Context.ReturnVarName}[i]);"); + + Context.Before.WriteCloseBraceIndent(); + + Context.Return.Write(intermediateArray); + } + private readonly CSharpTypePrinter typePrinter; } @@ -861,7 +907,7 @@ namespace CppSharp.Generators.CSharp return; } - var intermediateArray = $"__{Context.Parameter.Name}"; + var intermediateArray = Generator.GeneratedIdentifier(Context.Parameter.Name); var intermediateArrayType = typePrinter.PrintNative(arrayType); Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); @@ -876,7 +922,7 @@ namespace CppSharp.Generators.CSharp Context.Before.WriteLine($"for (int i = 0; i < {intermediateArray}.Length; i++)"); Context.Before.WriteStartBraceIndent(); - const string element = "__element"; + string element = Generator.GeneratedIdentifier("element"); Context.Before.WriteLine($"var {element} = {Context.Parameter.Name}[i];"); if (arrayType.IsAddress()) { diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index 4f136957..621a69be 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -1077,6 +1077,18 @@ public unsafe class CSharpTests : GeneratorTestFixture Assert.That(CSharp.CSharp.TakeConstStringArray(strings), Is.EqualTo("The test works.")); } + [Test] + public void TestArrayParamsInVirtual() + { + Foo[] pointers = { new Foo { A = 2 }, new Foo { A = 5 } }; + int[] ints = { 6, 7 }; + Foo[] values = { new Foo { A = 10 }, new Foo { A = 20 } }; + using (var qux = new Qux()) + { + Assert.That(qux.VirtualTakesArrays(pointers, ints, values), Is.EqualTo(50)); + } + } + private class OverrideVirtualTemplate : VirtualTemplate { public override int Function diff --git a/tests/CSharp/CSharp.cpp b/tests/CSharp/CSharp.cpp index c956816b..bb6058b1 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/CSharp/CSharp.cpp @@ -123,6 +123,28 @@ QColor::QColor(Qt::GlobalColor color) } +int takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) +{ + return arrayOfPointersToObjects[0]->A + arrayOfPointersToObjects[1]->A + + arrayOfPrimitives[0] + arrayOfPrimitives[1] + + arrayOfObjects[0].A + arrayOfObjects[1].A; +} + +std::string takeStringArray(const char* arrayOfStrings[]) +{ + std::string result; + for (int i = 0; i < 3; i++) + { + result += arrayOfStrings[i]; + } + return result; +} + +std::string takeConstStringArray(const char* const arrayOfStrings[]) +{ + return takeStringArray(const_cast(arrayOfStrings)); +} + Qux::Qux() { } @@ -162,8 +184,9 @@ void Qux::setInterface(Qux *qux) { } -void Qux::v(int array[]) +int Qux::virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const { + return takeArrays(arrayOfPointersToObjects, arrayOfPrimitives, arrayOfObjects); } Bar::Bar(Qux qux) @@ -1391,25 +1414,3 @@ typedefedFuncPtr* TestDuplicateDelegate::testDuplicateDelegate(int a) void InlineNamespace::FunctionInsideInlineNamespace() { } - -int takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) -{ - return arrayOfPointersToObjects[0]->A + arrayOfPointersToObjects[1]->A + - arrayOfPrimitives[0] + arrayOfPrimitives[1] + - arrayOfObjects[0].A + arrayOfObjects[1].A; -} - -std::string takeStringArray(const char* arrayOfStrings[]) -{ - std::string result; - for (int i = 0; i < 3; i++) - { - result += arrayOfStrings[i]; - } - return result; -} - -std::string takeConstStringArray(const char* const arrayOfStrings[]) -{ - return takeStringArray(const_cast(arrayOfStrings)); -} diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index c0b0e7a1..1babde44 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -50,6 +50,12 @@ private: class Bar; +DLL_API int takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]); + +DLL_API std::string takeStringArray(const char* arrayOfStrings[]); + +DLL_API std::string takeConstStringArray(const char* const arrayOfStrings[]); + class DLL_API Qux { public: @@ -62,7 +68,7 @@ public: void obsolete(); Qux* getInterface(); void setInterface(Qux* qux); - virtual void v(int array[]); + virtual int virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const; }; class DLL_API Bar : public Qux @@ -1236,9 +1242,3 @@ inline namespace InlineNamespace { DLL_API void FunctionInsideInlineNamespace(); } - -DLL_API int takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]); - -DLL_API std::string takeStringArray(const char* arrayOfStrings[]); - -DLL_API std::string takeConstStringArray(const char* const arrayOfStrings[]);