Browse Source

Added marshalling of parameters of type array of pointers.

Fixes https://github.com/mono/CppSharp/issues/932.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/943/head
Dimitar Dobrev 8 years ago
parent
commit
3d9cc3ab70
  1. 73
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 14
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  3. 7
      tests/CSharp/CSharp.Tests.cs
  4. 5
      tests/CSharp/CSharp.cpp
  5. 2
      tests/CSharp/CSharp.h

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

@ -426,6 +426,7 @@ namespace CppSharp.Generators.CSharp @@ -426,6 +426,7 @@ namespace CppSharp.Generators.CSharp
if (!VisitType(array, quals))
return false;
var arrayType = array.Type.Desugar();
switch (array.SizeType)
{
case ArrayType.ArraySize.Constant:
@ -447,8 +448,7 @@ namespace CppSharp.Generators.CSharp @@ -447,8 +448,7 @@ namespace CppSharp.Generators.CSharp
supportBefore.WriteLine("if ({0} != null)", Context.ArgName);
supportBefore.WriteStartBraceIndent();
Class @class;
var arrayType = array.Type.Desugar();
if (array.Type.Desugar().TryGetClass(out @class) && @class.IsRefType)
if (arrayType.TryGetClass(out @class) && @class.IsRefType)
{
supportBefore.WriteLine("if (value.Length != {0})", array.Size);
ThrowArgumentOutOfRangeException();
@ -458,7 +458,7 @@ namespace CppSharp.Generators.CSharp @@ -458,7 +458,7 @@ namespace CppSharp.Generators.CSharp
{
supportBefore.WriteLineIndent(
"*({1}.{2}*) &{0}[i * sizeof({1}.{2})] = *({1}.{2}*){3}[i].{4};",
Context.ReturnVarName, array.Type, Helpers.InternalStruct,
Context.ReturnVarName, arrayType, Helpers.InternalStruct,
Context.ArgName, Helpers.InstanceIdentifier);
}
else
@ -475,7 +475,7 @@ namespace CppSharp.Generators.CSharp @@ -475,7 +475,7 @@ namespace CppSharp.Generators.CSharp
supportBefore.WriteLineIndent("{0}[i] = {1}[i]{2};",
Context.ReturnVarName,
Context.ArgName,
array.Type.IsPointerToPrimitiveType(PrimitiveType.Void)
arrayType.IsPointerToPrimitiveType(PrimitiveType.Void)
? ".ToPointer()"
: string.Empty);
}
@ -484,7 +484,7 @@ namespace CppSharp.Generators.CSharp @@ -484,7 +484,7 @@ namespace CppSharp.Generators.CSharp
}
break;
case ArrayType.ArraySize.Incomplete:
Context.Return.Write(Context.Parameter.Name);
MarshalVariableArray(arrayType);
break;
default:
Context.Return.Write("null");
@ -493,21 +493,6 @@ namespace CppSharp.Generators.CSharp @@ -493,21 +493,6 @@ namespace CppSharp.Generators.CSharp
return true;
}
private void ThrowArgumentOutOfRangeException()
{
Context.Before.WriteLineIndent(
"throw new ArgumentOutOfRangeException(\"{0}\", " +
"\"The dimensions of the provided array don't match the required size.\");",
Context.Parameter.Name);
}
public bool VisitDelegateType(FunctionType function, string type)
{
Context.Return.Write("{0} == null ? global::System.IntPtr.Zero : Marshal.GetFunctionPointerForDelegate({0})",
Context.Parameter.Name);
return true;
}
public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
{
if (!VisitType(pointer, quals))
@ -572,7 +557,7 @@ namespace CppSharp.Generators.CSharp @@ -572,7 +557,7 @@ namespace CppSharp.Generators.CSharp
if (pointee is FunctionType)
{
var function = pointee as FunctionType;
return VisitDelegateType(function, function.ToString());
return VisitDelegateType();
}
Class @class;
@ -700,7 +685,7 @@ namespace CppSharp.Generators.CSharp @@ -700,7 +685,7 @@ namespace CppSharp.Generators.CSharp
FunctionType func;
if (decl.Type.IsPointerTo(out func))
{
VisitDelegateType(func, typedef.Declaration.OriginalName);
VisitDelegateType();
return true;
}
@ -855,6 +840,50 @@ namespace CppSharp.Generators.CSharp @@ -855,6 +840,50 @@ namespace CppSharp.Generators.CSharp
return template.TemplatedFunction.Visit(this);
}
private bool VisitDelegateType()
{
Context.Return.Write("{0} == null ? global::System.IntPtr.Zero : Marshal.GetFunctionPointerForDelegate({0})",
Context.Parameter.Name);
return true;
}
private void ThrowArgumentOutOfRangeException()
{
Context.Before.WriteLineIndent(
"throw new ArgumentOutOfRangeException(\"{0}\", " +
"\"The dimensions of the provided array don't match the required size.\");",
Context.Parameter.Name);
}
private void MarshalVariableArray(Type arrayType)
{
var intermediateArray = $"__{Context.Parameter.Name}";
var intermediateArrayType = typePrinter.PrintNative(arrayType);
const string intPtrType = CSharpTypePrinter.IntPtrType;
Context.Before.WriteLine($"{intermediateArrayType}[] {intermediateArray};");
Context.Before.WriteLine($"if (ReferenceEquals({Context.Parameter.Name}, null))");
Context.Before.WriteLineIndent($"{intermediateArray} = new[] {{ {intPtrType}.Zero }};");
Context.Before.WriteLine("else");
Context.Before.WriteStartBraceIndent();
Context.Before.WriteLine($@"{intermediateArray} = new {
intermediateArrayType}[{Context.Parameter.Name}.Length];");
Context.Before.WriteLine($"for (int i = 0; i < {intermediateArray}.Length; i++)");
Context.Before.WriteStartBraceIndent();
const string element = "__element";
Context.Before.WriteLine($"var {element} = {Context.Parameter.Name}[i];");
Context.Before.WriteLine($@"{intermediateArray}[i] = ReferenceEquals({
element}, null) ? {intPtrType}.Zero : {element}.{Helpers.InstanceIdentifier};");
Context.Before.WriteCloseBraceIndent();
Context.Before.WriteCloseBraceIndent();
Context.Return.Write(intermediateArray);
}
private readonly CSharpTypePrinter typePrinter;
}
}

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

@ -111,11 +111,11 @@ namespace CppSharp.Generators.CSharp @@ -111,11 +111,11 @@ namespace CppSharp.Generators.CSharp
arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int";
// Do not write the fixed keyword multiple times for nested array types
var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed ";
var fixedKeyword = arrayType is ArrayType ? string.Empty : "fixed ";
return new TypePrinterResult
{
Type = $"{fixedKeyword}{arrayElemType}",
NameSuffix = $"[{array.Size}]",
NameSuffix = $"[{array.Size}]"
};
}
@ -128,12 +128,10 @@ namespace CppSharp.Generators.CSharp @@ -128,12 +128,10 @@ namespace CppSharp.Generators.CSharp
if (arrayType.IsPointerToPrimitiveType(PrimitiveType.Char))
return "char**";
return string.Format("{0}{1}", array.Type.Visit(this),
array.SizeType == ArrayType.ArraySize.Constant ? "[]" :
(ContextKind == TypePrinterContextKind.Managed ? "*" : string.Empty));
// C# only supports fixed arrays in unsafe sections
// and they are constrained to a set of built-in types.
var arraySuffix = array.SizeType == ArrayType.ArraySize.Constant ||
!arrayType.IsPrimitiveType() ? "[]" :
(ContextKind == TypePrinterContextKind.Managed ? "*" : string.Empty);
return $"{arrayType.Visit(this)}{arraySuffix}";
}
public override TypePrinterResult VisitFunctionType(FunctionType function,

7
tests/CSharp/CSharp.Tests.cs

@ -1060,6 +1060,13 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -1060,6 +1060,13 @@ public unsafe class CSharpTests : GeneratorTestFixture
bar.Dispose();
}
[Test]
public void TestArrayParams()
{
Foo[] foos = { new Foo { A = 2 }, new Foo { A = 5 } };
Assert.That(CSharp.CSharp.TakeArrayOfPointersToObjects(foos), Is.EqualTo(7));
}
private class OverrideVirtualTemplate : VirtualTemplate<int>
{
public override int Function

5
tests/CSharp/CSharp.cpp

@ -1391,3 +1391,8 @@ typedefedFuncPtr* TestDuplicateDelegate::testDuplicateDelegate(int a) @@ -1391,3 +1391,8 @@ typedefedFuncPtr* TestDuplicateDelegate::testDuplicateDelegate(int a)
void InlineNamespace::FunctionInsideInlineNamespace()
{
}
int takeArrayOfPointersToObjects(Foo* arrayOfPointersToObjects[])
{
return arrayOfPointersToObjects[0]->A + arrayOfPointersToObjects[1]->A;
}

2
tests/CSharp/CSharp.h

@ -1236,3 +1236,5 @@ inline namespace InlineNamespace @@ -1236,3 +1236,5 @@ inline namespace InlineNamespace
{
DLL_API void FunctionInsideInlineNamespace();
}
DLL_API int takeArrayOfPointersToObjects(Foo* arrayOfPointersToObjects[]);

Loading…
Cancel
Save