Skip to content

Commit

Permalink
Support indirect parameters
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitar Dobrev <[email protected]>
  • Loading branch information
ddobrev authored and tritao committed Apr 27, 2019
1 parent 76ef6b0 commit a9bfe1c
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 26 deletions.
7 changes: 2 additions & 5 deletions src/CppParser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3286,14 +3286,11 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
F->isReturnIndirect = CGInfo.getReturnInfo().isIndirect();

unsigned Index = 0;
for (auto I = CGInfo.arg_begin(), E = CGInfo.arg_end(); I != E; I++)
for (const auto& Arg : CGInfo.arguments())
{
// Skip the first argument as it's the return type.
if (I == CGInfo.arg_begin())
continue;
if (Index >= F->Parameters.size())
continue;
F->Parameters[Index++]->isIndirect = I->info.isIndirect();
F->Parameters[Index++]->isIndirect = Arg.info.isIndirect();
}

MarkValidity(F);
Expand Down
4 changes: 4 additions & 0 deletions src/Generator/Generators/CSharp/CSharpMarshal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,10 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
}

pointer.QualifiedPointee.Visit(this);

if (Context.Parameter.IsIndirect)
Context.ArgumentPrefix.Write("&");

bool isVoid = primitive == PrimitiveType.Void &&
pointee.IsAddress() && pointer.IsReference();
if (pointer.Pointee.Desugar(false) is TemplateParameterSubstitutionType ||
Expand Down
19 changes: 4 additions & 15 deletions src/Generator/Generators/CSharp/CSharpTypePrinter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ public override TypePrinterResult VisitPointerType(PointerType pointer,
// * Any pointer type.
// * Any user-defined struct type that contains fields of unmanaged types only.
var finalPointee = (pointee.GetFinalPointee() ?? pointee).Desugar();
if (finalPointee.IsPrimitiveType())
Enumeration @enum;
if (finalPointee.IsPrimitiveType() || finalPointee.TryGetEnum(out @enum))
{
// Skip one indirection if passed by reference
bool isRefParam = Parameter != null && (Parameter.IsOut || Parameter.IsInOut);
Expand All @@ -220,18 +221,8 @@ public override TypePrinterResult VisitPointerType(PointerType pointer,
var result = pointer.QualifiedPointee.Visit(this);
allowStrings = true;

return !isRefParam && result.Type == IntPtrType ? "void**" : result + "*";
}

Enumeration @enum;
if (pointee.TryGetEnum(out @enum))
{
// Skip one indirection if passed by reference
if (isManagedContext && Parameter != null && (Parameter.IsOut || Parameter.IsInOut)
&& pointee == finalPointee)
return pointer.QualifiedPointee.Visit(this);

return pointer.QualifiedPointee.Visit(this) + "*";
string @ref = Parameter != null && Parameter.IsIndirect ? string.Empty : "*";
return !isRefParam && result.Type == this.IntPtrType ? "void**" : result + @ref;
}

Class @class;
Expand Down Expand Up @@ -738,8 +729,6 @@ private static string GetParameterUsage(ParameterUsage usage)

public override TypePrinterResult VisitFieldDecl(Field field)
{
var cSharpSourcesDummy = new CSharpSources(Context, new List<TranslationUnit>());

PushMarshalKind(MarshalKind.NativeField);
var fieldTypePrinted = field.QualifiedType.Visit(this);
PopMarshalKind();
Expand Down
9 changes: 8 additions & 1 deletion src/Generator/Passes/CheckAbiParameters.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using CppSharp.AST;
using CppSharp.AST.Extensions;
using System.Linq;

namespace CppSharp.Passes
{
Expand Down Expand Up @@ -79,7 +81,12 @@ public override bool VisitFunctionDecl(Function function)
});
}

// TODO: Handle indirect parameters
foreach (var param in from p in function.Parameters
where p.IsIndirect && !p.Type.Desugar().IsAddress()
select p)
{
param.QualifiedType = new QualifiedType(new PointerType(param.QualifiedType));
}

return true;
}
Expand Down
12 changes: 7 additions & 5 deletions tests/Common/Common.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -897,12 +897,14 @@ public void TestReturnChar16()
}
}

[Test, Ignore("Indirect parameters not supported yet")]
[Test]
public void TestStructWithCopyCtorByValue()
{
var structWithCopyCtor = new StructWithCopyCtor();
structWithCopyCtor.MBits = 10;
var ret = Common.TestStructWithCopyCtorByValue(structWithCopyCtor);
Assert.That(ret, Is.EqualTo(10));
using (var structWithCopyCtor = new StructWithCopyCtor())
{
structWithCopyCtor.MBits = 10;
var ret = Common.TestStructWithCopyCtorByValue(structWithCopyCtor);
Assert.That(ret, Is.EqualTo(10));
}
}
}

2 comments on commit a9bfe1c

@tritao
Copy link
Collaborator

@tritao tritao commented on a9bfe1c Apr 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Alan-FGR Thanks for bringing us that test case to our attention. 👍

CppSharp now supports interop with C++ indirect parameters ABI

@Alan-FGR
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're welcome. Awesome work guys! 👍

Please sign in to comment.