Browse Source

Fixed the generated C# when a virtual function takes a fixed array.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/955/head
Dimitar Dobrev 8 years ago
parent
commit
122359bf9e
  1. 70
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 1
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 25
      tests/CSharp/CSharp.Tests.cs
  4. 24
      tests/CSharp/CSharp.cpp
  5. 4
      tests/CSharp/CSharp.h

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

@ -82,43 +82,51 @@ namespace CppSharp.Generators.CSharp @@ -82,43 +82,51 @@ namespace CppSharp.Generators.CSharp
switch (array.SizeType)
{
case ArrayType.ArraySize.Constant:
var supportBefore = Context.Before;
string value = Generator.GeneratedIdentifier("value");
supportBefore.WriteLine("{0}[] {1} = null;", array.Type, value, array.Size);
supportBefore.WriteLine("if ({0} != null)", Context.ReturnVarName);
supportBefore.WriteStartBraceIndent();
supportBefore.WriteLine("{0} = new {1}[{2}];", value, array.Type, array.Size);
supportBefore.WriteLine("for (int i = 0; i < {0}; i++)", array.Size);
if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void))
supportBefore.WriteLineIndent("{0}[i] = new global::System.IntPtr({1}[i]);",
value, Context.ReturnVarName);
else
if (Context.MarshalKind == MarshalKind.NativeField ||
Context.MarshalKind == MarshalKind.ReturnVariableArray)
{
var arrayType = array.Type.Desugar();
Class @class;
if (arrayType.TryGetClass(out @class) && @class.IsRefType)
supportBefore.WriteLineIndent(
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));",
value, array.Type, Helpers.CreateInstanceIdentifier,
Helpers.InternalStruct, Context.ReturnVarName);
var supportBefore = Context.Before;
string value = Generator.GeneratedIdentifier("value");
supportBefore.WriteLine("{0}[] {1} = null;", array.Type, value, array.Size);
supportBefore.WriteLine("if ({0} != null)", Context.ReturnVarName);
supportBefore.WriteStartBraceIndent();
supportBefore.WriteLine("{0} = new {1}[{2}];", value, array.Type, array.Size);
supportBefore.WriteLine("for (int i = 0; i < {0}; i++)", array.Size);
if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void))
supportBefore.WriteLineIndent("{0}[i] = new global::System.IntPtr({1}[i]);",
value, Context.ReturnVarName);
else
{
if (arrayType.IsPrimitiveType(PrimitiveType.Char) &&
Context.Context.Options.MarshalCharAsManagedChar)
{
var arrayType = array.Type.Desugar();
Class @class;
if (arrayType.TryGetClass(out @class) && @class.IsRefType)
supportBefore.WriteLineIndent(
"{0}[i] = global::System.Convert.ToChar({1}[i]);",
value, Context.ReturnVarName);
}
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));",
value, array.Type, Helpers.CreateInstanceIdentifier,
Helpers.InternalStruct, Context.ReturnVarName);
else
{
supportBefore.WriteLineIndent("{0}[i] = {1}[i];",
value, Context.ReturnVarName);
if (arrayType.IsPrimitiveType(PrimitiveType.Char) &&
Context.Context.Options.MarshalCharAsManagedChar)
{
supportBefore.WriteLineIndent(
"{0}[i] = global::System.Convert.ToChar({1}[i]);",
value, Context.ReturnVarName);
}
else
{
supportBefore.WriteLineIndent("{0}[i] = {1}[i];",
value, Context.ReturnVarName);
}
}
}
supportBefore.WriteCloseBraceIndent();
Context.Return.Write(value);
}
else
{
goto case ArrayType.ArraySize.Incomplete;
}
supportBefore.WriteCloseBraceIndent();
Context.Return.Write(value);
break;
case ArrayType.ArraySize.Incomplete:
// const char* and const char[] are the same so we can use a string
@ -128,7 +136,7 @@ namespace CppSharp.Generators.CSharp @@ -128,7 +136,7 @@ namespace CppSharp.Generators.CSharp
{
QualifiedPointee = array.QualifiedType
}, quals);
MarshalVariableArray(array);
MarshalArray(array);
break;
case ArrayType.ArraySize.Variable:
Context.Return.Write(Context.ReturnVarName);
@ -384,11 +392,11 @@ namespace CppSharp.Generators.CSharp @@ -384,11 +392,11 @@ namespace CppSharp.Generators.CSharp
return ret;
}
private void MarshalVariableArray(ArrayType array)
private void MarshalArray(ArrayType array)
{
Type arrayType = array.Type.Desugar();
if (arrayType.IsPrimitiveType() ||
arrayType.IsPointerToPrimitiveType(PrimitiveType.Char) ||
arrayType.IsPointerToPrimitiveType() ||
Context.MarshalKind != MarshalKind.GenericDelegate)
{
Context.Return.Write(Context.ReturnVarName);

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

@ -1057,6 +1057,7 @@ namespace CppSharp.Generators.CSharp @@ -1057,6 +1057,7 @@ namespace CppSharp.Generators.CSharp
ArgName = var.Name,
ReturnType = new QualifiedType(var.Type)
};
ctx.PushMarshalKind(MarshalKind.ReturnVariableArray);
var prefix = string.Empty;
if (!isRefTypeArray && elementType == null)
ctx.ReturnVarName = $"*{ptr}";

25
tests/CSharp/CSharp.Tests.cs

@ -5,7 +5,6 @@ using System.Runtime.InteropServices; @@ -5,7 +5,6 @@ using System.Runtime.InteropServices;
using CppSharp.Utils;
using CSharp;
using NUnit.Framework;
using CSharp.Delegates;
public unsafe class CSharpTests : GeneratorTestFixture
{
@ -1069,29 +1068,35 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -1069,29 +1068,35 @@ public unsafe class CSharpTests : GeneratorTestFixture
using (var testArrays = new TestArrays())
{
Assert.That(testArrays.TakeArrays(pointers, ints, values), Is.EqualTo(50));
Assert.That(testArrays.VirtualTakeArrays(pointers, ints, values), Is.EqualTo(50));
}
}
[Test]
public void TestStringArrayParams()
public void TestFixedArrayParams()
{
string[] strings = { "The ", "test ", "works." };
Foo[] pointers = { new Foo { A = 2 }, new Foo { A = 5 }, new Foo { A = 7 } };
var int1 = 6;
var int2 = 7;
var int3 = 8;
var int4 = 9;
int[] ints = { int1, int2, int3, int4 };
int*[] intPointers = { &int1, &int2, &int3, &int4, &int1 };
using (var testArrays = new TestArrays())
{
Assert.That(testArrays.TakeStringArray(strings), Is.EqualTo("The test works."));
Assert.That(testArrays.TakeConstStringArray(strings), Is.EqualTo("The test works."));
Assert.That(testArrays.TakeArrays(pointers, ints, intPointers), Is.EqualTo(80));
Assert.That(testArrays.VirtualTakeArrays(pointers, ints, intPointers), Is.EqualTo(80));
}
}
[Test]
public void TestArrayParamsInVirtual()
public void TestStringArrayParams()
{
Foo[] pointers = { new Foo { A = 2 }, new Foo { A = 5 } };
int[] ints = { 6, 7 };
Foo[] values = { new Foo { A = 10 }, new Foo { A = 20 } };
string[] strings = { "The ", "test ", "works." };
using (var testArrays = new TestArrays())
{
Assert.That(testArrays.VirtualTakesArrays(pointers, ints, values), Is.EqualTo(50));
Assert.That(testArrays.TakeStringArray(strings), Is.EqualTo("The test works."));
Assert.That(testArrays.TakeConstStringArray(strings), Is.EqualTo("The test works."));
}
}

24
tests/CSharp/CSharp.cpp

@ -1410,9 +1410,20 @@ int TestArrays::takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitive @@ -1410,9 +1410,20 @@ int TestArrays::takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitive
int TestArrays::takeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4],
int* fixedArrayOfPointersToPrimitives[5]) const
{
return fixedArrayOfPointersToObjects[0]->A + fixedArrayOfPointersToObjects[1]->A +
fixedArrayOfPrimitives[0] + fixedArrayOfPrimitives[1] +
*fixedArrayOfPointersToPrimitives[0] + *fixedArrayOfPointersToPrimitives[1];
int sum = 0;
for (int i = 0; i < 3; i++)
{
sum += fixedArrayOfPointersToObjects[i]->A;
}
for (int i = 0; i < 4; i++)
{
sum += fixedArrayOfPrimitives[i];
}
for (int i = 0; i < 5; i++)
{
sum += *fixedArrayOfPointersToPrimitives[i];
}
return sum;
}
std::string TestArrays::takeStringArray(const char* arrayOfStrings[])
@ -1430,7 +1441,12 @@ std::string TestArrays::takeConstStringArray(const char* const arrayOfStrings[]) @@ -1430,7 +1441,12 @@ std::string TestArrays::takeConstStringArray(const char* const arrayOfStrings[])
return takeStringArray(const_cast<const char**>(arrayOfStrings));
}
int TestArrays::virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const
int TestArrays::virtualTakeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const
{
return takeArrays(arrayOfPointersToObjects, arrayOfPrimitives, arrayOfObjects);
}
int TestArrays::virtualTakeArrays(Foo *fixedArrayOfPointersToObjects[], int fixedArrayOfPrimitives[], int *fixedArrayOfPointersToPrimitives[]) const
{
return takeArrays(fixedArrayOfPointersToObjects, fixedArrayOfPrimitives, fixedArrayOfPointersToPrimitives);
}

4
tests/CSharp/CSharp.h

@ -1247,5 +1247,7 @@ public: @@ -1247,5 +1247,7 @@ public:
int* fixedArrayOfPointersToPrimitives[5]) const;
std::string takeStringArray(const char* arrayOfStrings[]);
std::string takeConstStringArray(const char* const arrayOfStrings[]);
virtual int virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const;
virtual int virtualTakeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const;
virtual int virtualTakeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4],
int* fixedArrayOfPointersToPrimitives[5]) const;
};

Loading…
Cancel
Save