Skip to content

Commit c85f605

Browse files
committed
Fixed the generated C# when a virtual function takes a fixed array.
Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
1 parent 3af63fb commit c85f605

5 files changed

Lines changed: 79 additions & 45 deletions

File tree

src/Generator/Generators/CSharp/CSharpMarshal.cs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -82,43 +82,51 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
8282
switch (array.SizeType)
8383
{
8484
case ArrayType.ArraySize.Constant:
85-
var supportBefore = Context.Before;
86-
string value = Generator.GeneratedIdentifier("value");
87-
supportBefore.WriteLine("{0}[] {1} = null;", array.Type, value, array.Size);
88-
supportBefore.WriteLine("if ({0} != null)", Context.ReturnVarName);
89-
supportBefore.WriteStartBraceIndent();
90-
supportBefore.WriteLine("{0} = new {1}[{2}];", value, array.Type, array.Size);
91-
supportBefore.WriteLine("for (int i = 0; i < {0}; i++)", array.Size);
92-
if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void))
93-
supportBefore.WriteLineIndent("{0}[i] = new global::System.IntPtr({1}[i]);",
94-
value, Context.ReturnVarName);
95-
else
85+
if (Context.MarshalKind == MarshalKind.NativeField ||
86+
Context.MarshalKind == MarshalKind.ReturnVariableArray)
9687
{
97-
var arrayType = array.Type.Desugar();
98-
Class @class;
99-
if (arrayType.TryGetClass(out @class) && @class.IsRefType)
100-
supportBefore.WriteLineIndent(
101-
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));",
102-
value, array.Type, Helpers.CreateInstanceIdentifier,
103-
Helpers.InternalStruct, Context.ReturnVarName);
88+
var supportBefore = Context.Before;
89+
string value = Generator.GeneratedIdentifier("value");
90+
supportBefore.WriteLine("{0}[] {1} = null;", array.Type, value, array.Size);
91+
supportBefore.WriteLine("if ({0} != null)", Context.ReturnVarName);
92+
supportBefore.WriteStartBraceIndent();
93+
supportBefore.WriteLine("{0} = new {1}[{2}];", value, array.Type, array.Size);
94+
supportBefore.WriteLine("for (int i = 0; i < {0}; i++)", array.Size);
95+
if (array.Type.IsPointerToPrimitiveType(PrimitiveType.Void))
96+
supportBefore.WriteLineIndent("{0}[i] = new global::System.IntPtr({1}[i]);",
97+
value, Context.ReturnVarName);
10498
else
10599
{
106-
if (arrayType.IsPrimitiveType(PrimitiveType.Char) &&
107-
Context.Context.Options.MarshalCharAsManagedChar)
108-
{
100+
var arrayType = array.Type.Desugar();
101+
Class @class;
102+
if (arrayType.TryGetClass(out @class) && @class.IsRefType)
109103
supportBefore.WriteLineIndent(
110-
"{0}[i] = global::System.Convert.ToChar({1}[i]);",
111-
value, Context.ReturnVarName);
112-
}
104+
"{0}[i] = {1}.{2}(*(({1}.{3}*)&({4}[i * sizeof({1}.{3})])));",
105+
value, array.Type, Helpers.CreateInstanceIdentifier,
106+
Helpers.InternalStruct, Context.ReturnVarName);
113107
else
114108
{
115-
supportBefore.WriteLineIndent("{0}[i] = {1}[i];",
116-
value, Context.ReturnVarName);
109+
if (arrayType.IsPrimitiveType(PrimitiveType.Char) &&
110+
Context.Context.Options.MarshalCharAsManagedChar)
111+
{
112+
supportBefore.WriteLineIndent(
113+
"{0}[i] = global::System.Convert.ToChar({1}[i]);",
114+
value, Context.ReturnVarName);
115+
}
116+
else
117+
{
118+
supportBefore.WriteLineIndent("{0}[i] = {1}[i];",
119+
value, Context.ReturnVarName);
120+
}
117121
}
118122
}
123+
supportBefore.WriteCloseBraceIndent();
124+
Context.Return.Write(value);
125+
}
126+
else
127+
{
128+
goto case ArrayType.ArraySize.Incomplete;
119129
}
120-
supportBefore.WriteCloseBraceIndent();
121-
Context.Return.Write(value);
122130
break;
123131
case ArrayType.ArraySize.Incomplete:
124132
// const char* and const char[] are the same so we can use a string
@@ -128,7 +136,7 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
128136
{
129137
QualifiedPointee = array.QualifiedType
130138
}, quals);
131-
MarshalVariableArray(array);
139+
MarshalArray(array);
132140
break;
133141
case ArrayType.ArraySize.Variable:
134142
Context.Return.Write(Context.ReturnVarName);
@@ -384,11 +392,11 @@ private string HandleReturnedPointer(Class @class, string qualifiedClass)
384392
return ret;
385393
}
386394

387-
private void MarshalVariableArray(ArrayType array)
395+
private void MarshalArray(ArrayType array)
388396
{
389397
Type arrayType = array.Type.Desugar();
390398
if (arrayType.IsPrimitiveType() ||
391-
arrayType.IsPointerToPrimitiveType(PrimitiveType.Char) ||
399+
arrayType.IsPointerToPrimitiveType() ||
392400
Context.MarshalKind != MarshalKind.GenericDelegate)
393401
{
394402
Context.Return.Write(Context.ReturnVarName);

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,7 @@ private void GenerateVariableGetter(Variable var)
10571057
ArgName = var.Name,
10581058
ReturnType = new QualifiedType(var.Type)
10591059
};
1060+
ctx.PushMarshalKind(MarshalKind.ReturnVariableArray);
10601061
var prefix = string.Empty;
10611062
if (!isRefTypeArray && elementType == null)
10621063
ctx.ReturnVarName = $"*{ptr}";

tests/CSharp/CSharp.Tests.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using CSharp;
77
using NUnit.Framework;
88
using CSharp.Delegates;
9+
using System.Linq;
910

1011
public unsafe class CSharpTests : GeneratorTestFixture
1112
{
@@ -1069,29 +1070,35 @@ public void TestArrayParams()
10691070
using (var testArrays = new TestArrays())
10701071
{
10711072
Assert.That(testArrays.TakeArrays(pointers, ints, values), Is.EqualTo(50));
1073+
Assert.That(testArrays.VirtualTakeArrays(pointers, ints, values), Is.EqualTo(50));
10721074
}
10731075
}
10741076

10751077
[Test]
1076-
public void TestStringArrayParams()
1078+
public void TestFixedArrayParams()
10771079
{
1078-
string[] strings = { "The ", "test ", "works." };
1080+
Foo[] pointers = { new Foo { A = 2 }, new Foo { A = 5 }, new Foo { A = 7 } };
1081+
var int1 = 6;
1082+
var int2 = 7;
1083+
var int3 = 8;
1084+
var int4 = 9;
1085+
int[] ints = { int1, int2, int3, int4 };
1086+
int*[] intPointers = { &int1, &int2, &int3, &int4, &int1 };
10791087
using (var testArrays = new TestArrays())
10801088
{
1081-
Assert.That(testArrays.TakeStringArray(strings), Is.EqualTo("The test works."));
1082-
Assert.That(testArrays.TakeConstStringArray(strings), Is.EqualTo("The test works."));
1089+
Assert.That(testArrays.TakeArrays(pointers, ints, intPointers), Is.EqualTo(80));
1090+
Assert.That(testArrays.VirtualTakeArrays(pointers, ints, intPointers), Is.EqualTo(80));
10831091
}
10841092
}
10851093

10861094
[Test]
1087-
public void TestArrayParamsInVirtual()
1095+
public void TestStringArrayParams()
10881096
{
1089-
Foo[] pointers = { new Foo { A = 2 }, new Foo { A = 5 } };
1090-
int[] ints = { 6, 7 };
1091-
Foo[] values = { new Foo { A = 10 }, new Foo { A = 20 } };
1097+
string[] strings = { "The ", "test ", "works." };
10921098
using (var testArrays = new TestArrays())
10931099
{
1094-
Assert.That(testArrays.VirtualTakesArrays(pointers, ints, values), Is.EqualTo(50));
1100+
Assert.That(testArrays.TakeStringArray(strings), Is.EqualTo("The test works."));
1101+
Assert.That(testArrays.TakeConstStringArray(strings), Is.EqualTo("The test works."));
10951102
}
10961103
}
10971104

tests/CSharp/CSharp.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,9 +1410,20 @@ int TestArrays::takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitive
14101410
int TestArrays::takeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4],
14111411
int* fixedArrayOfPointersToPrimitives[5]) const
14121412
{
1413-
return fixedArrayOfPointersToObjects[0]->A + fixedArrayOfPointersToObjects[1]->A +
1414-
fixedArrayOfPrimitives[0] + fixedArrayOfPrimitives[1] +
1415-
*fixedArrayOfPointersToPrimitives[0] + *fixedArrayOfPointersToPrimitives[1];
1413+
int sum = 0;
1414+
for (int i = 0; i < 3; i++)
1415+
{
1416+
sum += fixedArrayOfPointersToObjects[i]->A;
1417+
}
1418+
for (int i = 0; i < 4; i++)
1419+
{
1420+
sum += fixedArrayOfPrimitives[i];
1421+
}
1422+
for (int i = 0; i < 5; i++)
1423+
{
1424+
sum += *fixedArrayOfPointersToPrimitives[i];
1425+
}
1426+
return sum;
14161427
}
14171428

14181429
std::string TestArrays::takeStringArray(const char* arrayOfStrings[])
@@ -1430,7 +1441,12 @@ std::string TestArrays::takeConstStringArray(const char* const arrayOfStrings[])
14301441
return takeStringArray(const_cast<const char**>(arrayOfStrings));
14311442
}
14321443

1433-
int TestArrays::virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const
1444+
int TestArrays::virtualTakeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const
14341445
{
14351446
return takeArrays(arrayOfPointersToObjects, arrayOfPrimitives, arrayOfObjects);
14361447
}
1448+
1449+
int TestArrays::virtualTakeArrays(Foo *fixedArrayOfPointersToObjects[], int fixedArrayOfPrimitives[], int *fixedArrayOfPointersToPrimitives[]) const
1450+
{
1451+
return takeArrays(fixedArrayOfPointersToObjects, fixedArrayOfPrimitives, fixedArrayOfPointersToPrimitives);
1452+
}

tests/CSharp/CSharp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1247,5 +1247,7 @@ class DLL_API TestArrays
12471247
int* fixedArrayOfPointersToPrimitives[5]) const;
12481248
std::string takeStringArray(const char* arrayOfStrings[]);
12491249
std::string takeConstStringArray(const char* const arrayOfStrings[]);
1250-
virtual int virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const;
1250+
virtual int virtualTakeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const;
1251+
virtual int virtualTakeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4],
1252+
int* fixedArrayOfPointersToPrimitives[5]) const;
12511253
};

0 commit comments

Comments
 (0)