Browse Source

Fixed the generated C# for fixed arrays in types of parameters.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/955/head
Dimitar Dobrev 8 years ago
parent
commit
3af63fb33d
  1. 31
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 7
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  3. 2
      src/Generator/Passes/CheckIgnoredDecls.cs
  4. 30
      src/Generator/Types/TypeIgnoreChecker.cs
  5. 8
      tests/CSharp/CSharp.cpp
  6. 2
      tests/CSharp/CSharp.h

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

@ -478,15 +478,7 @@ namespace CppSharp.Generators.CSharp
case ArrayType.ArraySize.Constant: case ArrayType.ArraySize.Constant:
if (string.IsNullOrEmpty(Context.ReturnVarName)) if (string.IsNullOrEmpty(Context.ReturnVarName))
{ {
Context.Before.WriteLine("if ({0} == null || {0}.Length != {1})", goto case ArrayType.ArraySize.Incomplete;
Context.Parameter.Name, array.Size);
ThrowArgumentOutOfRangeException();
var ptr = "__ptr" + Context.ParameterIndex;
Context.Before.WriteLine("fixed ({0}* {1} = {2})",
array.Type, ptr, Context.Parameter.Name);
Context.Before.WriteStartBraceIndent();
Context.Return.Write("new global::System.IntPtr({0})", ptr);
Context.HasCodeBlock = true;
} }
else else
{ {
@ -530,7 +522,7 @@ namespace CppSharp.Generators.CSharp
} }
break; break;
case ArrayType.ArraySize.Incomplete: case ArrayType.ArraySize.Incomplete:
MarshalVariableArray(arrayType); MarshalArray(array);
break; break;
default: default:
Context.Return.Write("null"); Context.Return.Write("null");
@ -898,17 +890,26 @@ namespace CppSharp.Generators.CSharp
Context.Parameter.Name); Context.Parameter.Name);
} }
private void MarshalVariableArray(Type arrayType) private void MarshalArray(ArrayType arrayType)
{ {
if (arrayType.IsPrimitiveType() || if (arrayType.SizeType == ArrayType.ArraySize.Constant)
arrayType.IsPointerToPrimitiveType(PrimitiveType.Char)) {
Context.Before.WriteLine("if ({0} == null || {0}.Length != {1})",
Context.Parameter.Name, arrayType.Size);
ThrowArgumentOutOfRangeException();
}
var elementType = arrayType.Type.Desugar();
if (elementType.IsPrimitiveType() ||
elementType.IsPointerToPrimitiveType())
{ {
Context.Return.Write(Context.Parameter.Name); Context.Return.Write(Context.Parameter.Name);
return; return;
} }
var intermediateArray = Generator.GeneratedIdentifier(Context.Parameter.Name); var intermediateArray = Generator.GeneratedIdentifier(Context.Parameter.Name);
var intermediateArrayType = typePrinter.PrintNative(arrayType); var intermediateArrayType = typePrinter.PrintNative(elementType);
Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};"); Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};");
@ -924,7 +925,7 @@ namespace CppSharp.Generators.CSharp
Context.Before.WriteStartBraceIndent(); Context.Before.WriteStartBraceIndent();
string element = Generator.GeneratedIdentifier("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 (elementType.IsAddress())
{ {
var intPtrZero = $"{CSharpTypePrinter.IntPtrType}.Zero"; var intPtrZero = $"{CSharpTypePrinter.IntPtrType}.Zero";
Context.Before.WriteLine($@"{intermediateArray}[i] = ReferenceEquals({ Context.Before.WriteLine($@"{intermediateArray}[i] = ReferenceEquals({

7
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -60,7 +60,9 @@ namespace CppSharp.Generators.CSharp
TypeQualifiers quals) TypeQualifiers quals)
{ {
Type arrayType = array.Type.Desugar(); Type arrayType = array.Type.Desugar();
if (ContextKind == TypePrinterContextKind.Native && if ((MarshalKind == MarshalKind.NativeField ||
(ContextKind == TypePrinterContextKind.Native &&
MarshalKind == MarshalKind.ReturnVariableArray)) &&
array.SizeType == ArrayType.ArraySize.Constant) array.SizeType == ArrayType.ArraySize.Constant)
{ {
if (array.Size == 0) if (array.Size == 0)
@ -278,8 +280,7 @@ namespace CppSharp.Generators.CSharp
} }
Class @class; Class @class;
if ((desugared.IsDependent || desugared.TryGetClass(out @class) || if ((desugared.IsDependent || desugared.TryGetClass(out @class))
(desugared is ArrayType && Parameter != null))
&& ContextKind == TypePrinterContextKind.Native) && ContextKind == TypePrinterContextKind.Native)
{ {
return IntPtrType; return IntPtrType;

2
src/Generator/Passes/CheckIgnoredDecls.cs

@ -472,7 +472,7 @@ namespace CppSharp.Passes
private bool IsTypeIgnored(Type type) private bool IsTypeIgnored(Type type)
{ {
var checker = new TypeIgnoreChecker(TypeMaps); var checker = new TypeIgnoreChecker(TypeMaps, Options.GeneratorKind);
type.Visit(checker); type.Visit(checker);
return checker.IsIgnored; return checker.IsIgnored;

30
src/Generator/Types/TypeIgnoreChecker.cs

@ -1,5 +1,6 @@
using CppSharp.AST; using CppSharp.AST;
using CppSharp.AST.Extensions; using CppSharp.AST.Extensions;
using CppSharp.Generators;
using CppSharp.Types; using CppSharp.Types;
namespace CppSharp namespace CppSharp
@ -9,14 +10,16 @@ namespace CppSharp
/// </summary> /// </summary>
public class TypeIgnoreChecker : AstVisitor public class TypeIgnoreChecker : AstVisitor
{ {
ITypeMapDatabase TypeMapDatabase { get; set; } ITypeMapDatabase TypeMapDatabase { get; }
public bool IsIgnored; public bool IsIgnored;
public TypeIgnoreChecker(ITypeMapDatabase database) public TypeIgnoreChecker(ITypeMapDatabase database,
GeneratorKind generatorKind = GeneratorKind.CSharp)
{ {
TypeMapDatabase = database; TypeMapDatabase = database;
VisitOptions.VisitClassBases = false; VisitOptions.VisitClassBases = false;
VisitOptions.VisitTemplateArguments = false; VisitOptions.VisitTemplateArguments = false;
this.generatorKind = generatorKind;
} }
void Ignore() void Ignore()
@ -138,14 +141,29 @@ namespace CppSharp
return false; return false;
} }
var arrayElemType = array.Type.Desugar();
Enumeration @enum;
FunctionType functionType;
if (arrayElemType is ArrayType ||
arrayElemType is FunctionType ||
arrayElemType.IsPointerTo(out functionType) ||
(arrayElemType.TryGetEnum(out @enum) &&
array.SizeType == ArrayType.ArraySize.Constant))
{
Ignore();
return false;
}
if (generatorKind == GeneratorKind.CSharp)
return true;
// the C++/CLI generator needs work to support arrays
if (!array.QualifiedType.Visit(this)) if (!array.QualifiedType.Visit(this))
return false; return false;
if (array.SizeType != ArrayType.ArraySize.Constant) if (array.SizeType != ArrayType.ArraySize.Constant)
return true; return true;
var arrayElemType = array.Type.Desugar();
Class @class; Class @class;
if (arrayElemType.TryGetClass(out @class) && @class.IsRefType) if (arrayElemType.TryGetClass(out @class) && @class.IsRefType)
return true; return true;
@ -170,6 +188,8 @@ namespace CppSharp
Ignore(); Ignore();
return false; return false;
} }
}
private readonly GeneratorKind generatorKind;
}
} }

8
tests/CSharp/CSharp.cpp

@ -1407,6 +1407,14 @@ int TestArrays::takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitive
arrayOfObjects[0].A + arrayOfObjects[1].A; arrayOfObjects[0].A + arrayOfObjects[1].A;
} }
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];
}
std::string TestArrays::takeStringArray(const char* arrayOfStrings[]) std::string TestArrays::takeStringArray(const char* arrayOfStrings[])
{ {
std::string result; std::string result;

2
tests/CSharp/CSharp.h

@ -1243,6 +1243,8 @@ public:
TestArrays(); TestArrays();
~TestArrays(); ~TestArrays();
int takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const; int takeArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const;
int takeArrays(Foo* fixedArrayOfPointersToObjects[3], int fixedArrayOfPrimitives[4],
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 virtualTakesArrays(Foo* arrayOfPointersToObjects[], int arrayOfPrimitives[], Foo arrayOfObjects[]) const;

Loading…
Cancel
Save