Browse Source

Fixed the generated C# for virtuals taking arrays of objects.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/955/head
Dimitar Dobrev 8 years ago
parent
commit
f6033f3a5a
  1. 54
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 12
      tests/CSharp/CSharp.Tests.cs
  3. 47
      tests/CSharp/CSharp.cpp
  4. 14
      tests/CSharp/CSharp.h

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

@ -128,8 +128,8 @@ namespace CppSharp.Generators.CSharp
{ {
QualifiedPointee = array.QualifiedType QualifiedPointee = array.QualifiedType
}, quals); }, quals);
MarshalVariableArray(array);
goto case ArrayType.ArraySize.Variable; break;
case ArrayType.ArraySize.Variable: case ArrayType.ArraySize.Variable:
Context.Return.Write(Context.ReturnVarName); Context.Return.Write(Context.ReturnVarName);
break; break;
@ -384,6 +384,52 @@ namespace CppSharp.Generators.CSharp
return ret; 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; private readonly CSharpTypePrinter typePrinter;
} }
@ -861,7 +907,7 @@ namespace CppSharp.Generators.CSharp
return; return;
} }
var intermediateArray = $"__{Context.Parameter.Name}"; var intermediateArray = Generator.GeneratedIdentifier(Context.Parameter.Name);
var intermediateArrayType = typePrinter.PrintNative(arrayType); var intermediateArrayType = typePrinter.PrintNative(arrayType);
Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); 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.WriteLine($"for (int i = 0; i < {intermediateArray}.Length; i++)");
Context.Before.WriteStartBraceIndent(); Context.Before.WriteStartBraceIndent();
const string element = "__element"; string element = Generator.GeneratedIdentifier("element");
Context.Before.WriteLine($"var {element} = {Context.Parameter.Name}[i];"); Context.Before.WriteLine($"var {element} = {Context.Parameter.Name}[i];");
if (arrayType.IsAddress()) if (arrayType.IsAddress())
{ {

12
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.")); 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<int> private class OverrideVirtualTemplate : VirtualTemplate<int>
{ {
public override int Function public override int Function

47
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<const char**>(arrayOfStrings));
}
Qux::Qux() 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) Bar::Bar(Qux qux)
@ -1391,25 +1414,3 @@ typedefedFuncPtr* TestDuplicateDelegate::testDuplicateDelegate(int a)
void InlineNamespace::FunctionInsideInlineNamespace() 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<const char**>(arrayOfStrings));
}

14
tests/CSharp/CSharp.h

@ -50,6 +50,12 @@ private:
class Bar; 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 class DLL_API Qux
{ {
public: public:
@ -62,7 +68,7 @@ public:
void obsolete(); void obsolete();
Qux* getInterface(); Qux* getInterface();
void setInterface(Qux* qux); 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 class DLL_API Bar : public Qux
@ -1236,9 +1242,3 @@ inline namespace InlineNamespace
{ {
DLL_API void FunctionInsideInlineNamespace(); 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[]);

Loading…
Cancel
Save