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

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

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

25
tests/CSharp/CSharp.Tests.cs

@ -5,7 +5,6 @@ using System.Runtime.InteropServices;
using CppSharp.Utils; using CppSharp.Utils;
using CSharp; using CSharp;
using NUnit.Framework; using NUnit.Framework;
using CSharp.Delegates;
public unsafe class CSharpTests : GeneratorTestFixture public unsafe class CSharpTests : GeneratorTestFixture
{ {
@ -1069,29 +1068,35 @@ public unsafe class CSharpTests : GeneratorTestFixture
using (var testArrays = new TestArrays()) using (var testArrays = new TestArrays())
{ {
Assert.That(testArrays.TakeArrays(pointers, ints, values), Is.EqualTo(50)); Assert.That(testArrays.TakeArrays(pointers, ints, values), Is.EqualTo(50));
Assert.That(testArrays.VirtualTakeArrays(pointers, ints, values), Is.EqualTo(50));
} }
} }
[Test] [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()) using (var testArrays = new TestArrays())
{ {
Assert.That(testArrays.TakeStringArray(strings), Is.EqualTo("The test works.")); Assert.That(testArrays.TakeArrays(pointers, ints, intPointers), Is.EqualTo(80));
Assert.That(testArrays.TakeConstStringArray(strings), Is.EqualTo("The test works.")); Assert.That(testArrays.VirtualTakeArrays(pointers, ints, intPointers), Is.EqualTo(80));
} }
} }
[Test] [Test]
public void TestArrayParamsInVirtual() public void TestStringArrayParams()
{ {
Foo[] pointers = { new Foo { A = 2 }, new Foo { A = 5 } }; string[] strings = { "The ", "test ", "works." };
int[] ints = { 6, 7 };
Foo[] values = { new Foo { A = 10 }, new Foo { A = 20 } };
using (var testArrays = new TestArrays()) 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
int TestArrays::takeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4], int TestArrays::takeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4],
int* fixedArrayOfPointersToPrimitives[5]) const int* fixedArrayOfPointersToPrimitives[5]) const
{ {
return fixedArrayOfPointersToObjects[0]->A + fixedArrayOfPointersToObjects[1]->A + int sum = 0;
fixedArrayOfPrimitives[0] + fixedArrayOfPrimitives[1] + for (int i = 0; i < 3; i++)
*fixedArrayOfPointersToPrimitives[0] + *fixedArrayOfPointersToPrimitives[1]; {
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[]) std::string TestArrays::takeStringArray(const char* arrayOfStrings[])
@ -1430,7 +1441,12 @@ std::string TestArrays::takeConstStringArray(const char* const arrayOfStrings[])
return takeStringArray(const_cast<const char**>(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); 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:
int* fixedArrayOfPointersToPrimitives[5]) const; int* fixedArrayOfPointersToPrimitives[5]) const;
std::string takeStringArray(const char* arrayOfStrings[]); std::string takeStringArray(const char* arrayOfStrings[]);
std::string takeConstStringArray(const char* const 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