Skip to content

Commit

Permalink
Added marshalling of primitive ptrs to ref type.
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitar Dobrev <[email protected]>
  • Loading branch information
genuinelucifer authored and ddobrev committed Aug 4, 2015
1 parent c8da628 commit d45e2da
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/Generator/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ public void SetupPasses(ILibrary library)
TranslationUnitPasses.AddPass(new SortDeclarationsPass());
TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass());
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass());

if (Options.IsCSharpGenerator && Options.GenerateInlines)
TranslationUnitPasses.AddPass(new GenerateInlinesCodePass());
Expand Down
57 changes: 48 additions & 9 deletions src/Generator/Generators/CSharp/CSharpTextTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2146,16 +2146,39 @@ public void GenerateMethod(Method method, Class @class)
PopBlock(NewLineKind.BeforeNextBlock);
}

private static string OverloadParamNameWithDefValue(Parameter p, ref int index)
{
return (p.Type.IsPointerToPrimitiveType() && p.Usage == ParameterUsage.InOut && p.HasDefaultValue)
? "ref param" + index++
: p.DefaultArgument.String;
}

private void GenerateOverloadCall(Function function)
{
Type type = function.OriginalReturnType.Type;
for (int i = 0, j = 0; i < function.Parameters.Count; i++)
{
var parameter = function.Parameters[i];
PrimitiveType primitiveType;
if (parameter.Kind == ParameterKind.Regular && parameter.Ignore &&
parameter.Type.IsPointerToPrimitiveType(out primitiveType) &&
parameter.Usage == ParameterUsage.InOut && parameter.HasDefaultValue)
{
var pointeeType = ((PointerType) parameter.Type).Pointee.ToString();
WriteLine("{0} param{1} = {2};", pointeeType, j++,
primitiveType == PrimitiveType.Bool ? "false" : "0");
}
}

var index = 0;
var type = function.OriginalReturnType.Type;
WriteLine("{0}{1}({2});",
type.IsPrimitiveType(PrimitiveType.Void) ? string.Empty : "return ",
function.Name,
string.Join(", ",
function.Parameters.Where(
p => p.Kind == ParameterKind.Regular).Select(
p => p.Ignore ? p.DefaultArgument.String : p.Name)));
p => p.Ignore ? OverloadParamNameWithDefValue(p, ref index) :
(p.Usage == ParameterUsage.InOut ? "ref " : string.Empty) + p.Name)));
}

private void GenerateEquals(Function method, Class @class)
Expand Down Expand Up @@ -2498,6 +2521,10 @@ into context

if (needsFixedThis && operatorParam == null)
WriteCloseBraceIndent();

var numFixedBlocks = @params.Count(param => param.HasFixedBlock);
for(var i = 0; i < numFixedBlocks; ++i)
WriteCloseBraceIndent();
}

private int GetInstanceParamIndex(Method method)
Expand All @@ -2519,6 +2546,8 @@ private void GenerateFunctionCallOutParams(IEnumerable<ParamMarshal> @params,
{
var param = paramInfo.Param;
if (!(param.IsOut || param.IsInOut)) continue;
if (param.IsPrimitiveParameterConvertibleToRef())
continue;

var nativeVarName = paramInfo.Name;

Expand Down Expand Up @@ -2548,6 +2577,7 @@ public struct ParamMarshal
public string Name;
public Parameter Param;
public CSharpMarshalContext Context;
public bool HasFixedBlock;
}

public List<ParamMarshal> GenerateFunctionParamsMarshal(IEnumerable<Parameter> @params,
Expand Down Expand Up @@ -2601,16 +2631,25 @@ private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramInde

paramMarshal.Context = ctx;

var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
param.CSharpMarshalToNative(marshal);
if (param.IsPrimitiveParameterConvertibleToRef())
{
WriteLine("fixed({0} {1} = &{2})", param.Type.CSharpType(TypePrinter), argName, param.Name);
paramMarshal.HasFixedBlock = true;
WriteStartBraceIndent();
}
else
{
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
param.CSharpMarshalToNative(marshal);

if (string.IsNullOrEmpty(marshal.Context.Return))
throw new Exception("Cannot marshal argument of function");
if (string.IsNullOrEmpty(marshal.Context.Return))
throw new Exception("Cannot marshal argument of function");

if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);

WriteLine("var {0} = {1};", argName, marshal.Context.Return);
WriteLine("var {0} = {1};", argName, marshal.Context.Return);
}

return paramMarshal;
}
Expand Down
25 changes: 24 additions & 1 deletion src/Generator/Generators/ExtensionMethods.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using CppSharp.AST;
using System.Linq;
using System.Collections.Generic;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using Interop = System.Runtime.InteropServices;

namespace CppSharp.Generators
Expand All @@ -23,5 +26,25 @@ public static Interop.CallingConvention ToInteropCallConv(this CallingConvention

return Interop.CallingConvention.Winapi;
}

public static bool IsPrimitiveParameterConvertibleToRef(this Parameter param)
{
var allowedToHaveDefaultPtrVals = new List<PrimitiveType>
{
PrimitiveType.Bool,
PrimitiveType.Double,
PrimitiveType.Float,
PrimitiveType.Int,
PrimitiveType.Long,
PrimitiveType.LongLong,
PrimitiveType.Short,
PrimitiveType.UInt,
PrimitiveType.ULong,
PrimitiveType.ULongLong,
PrimitiveType.UShort
};
return param.Type.IsPointerToPrimitiveType()
&& allowedToHaveDefaultPtrVals.Any(primType => param.Type.IsPointerToPrimitiveType(primType));
}
}
}
12 changes: 9 additions & 3 deletions src/Generator/Passes/HandleDefaultParamValuesPass.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators;
using CppSharp.Generators.CSharp;
using CppSharp.Types;

Expand Down Expand Up @@ -52,7 +54,8 @@ public override bool VisitFunctionDecl(Function function)
parameter.QualifiedType.Qualifiers);
if (defaultConstruct == null ||
(!Driver.Options.MarshalCharAsManagedChar &&
parameter.Type.Desugar().IsPrimitiveType(PrimitiveType.UChar)))
parameter.Type.Desugar().IsPrimitiveType(PrimitiveType.UChar)) ||
parameter.IsPrimitiveParameterConvertibleToRef())
{
overloadIndices.Add(function.Parameters.IndexOf(parameter));
continue;
Expand Down Expand Up @@ -103,6 +106,8 @@ private bool CheckForDefaultPointer(Type desugared, Parameter parameter)
parameter.DefaultArgument.String = "new global::System.IntPtr()";
return true;
}
if (parameter.IsPrimitiveParameterConvertibleToRef())
return false;
Class @class;
if (desugared.GetFinalPointee().TryGetClass(out @class) && @class.IsValueType)
{
Expand Down Expand Up @@ -243,9 +248,10 @@ private void GenerateOverloads(Function function, List<int> overloadIndices)
Function overload = method != null ? new Method(method) : new Function(function);
overload.OriginalFunction = function;
overload.SynthKind = FunctionSynthKind.DefaultValueOverload;
overload.Parameters[overloadIndex].GenerationKind = GenerationKind.None;
for (int i = overloadIndex; i < function.Parameters.Count; ++i)
overload.Parameters[i].GenerationKind = GenerationKind.None;

var indices = overloadIndices.Where(i => i != overloadIndex).ToList();
var indices = overloadIndices.Where(i => i < overloadIndex).ToList();
if (indices.Any())
for (int i = 0; i <= indices.Last(); i++)
if (i != overloadIndex)
Expand Down
17 changes: 17 additions & 0 deletions src/Generator/Passes/MarshalPrimitivePointersAsRefTypePass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators;

namespace CppSharp.Passes
{
public class MarshalPrimitivePointersAsRefTypePass : TranslationUnitPass
{
public override bool VisitFunctionDecl(Function function)
{
foreach (var param in function.Parameters.Where(
p => !p.IsOut && p.IsPrimitiveParameterConvertibleToRef()))
param.Usage = ParameterUsage.InOut;
return base.VisitFunctionDecl(function);
}
}
}
36 changes: 35 additions & 1 deletion tests/CSharpTemp/CSharpTemp.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,4 +345,38 @@ public void TestNullAttributedFunctionPtr()
foo.AttributedFunctionPtr = null;
}
}
}

[Test]
public unsafe void TestMultiOverLoadPtrToRef()
{
var obj = new MultiOverloadPtrToRef();
var p = obj.ReturnPrimTypePtr();
Assert.AreEqual(0, p[0]);
Assert.AreEqual(0, p[1]);
Assert.AreEqual(0, p[2]);

obj.TakePrimTypePtr(ref *p);
Assert.AreEqual(100, p[0]);
Assert.AreEqual(200, p[1]);
Assert.AreEqual(300, p[2]);

int[] array = { 1, 2, 3 };
fixed (int* p1 = array)
{
obj.TakePrimTypePtr(ref *p1);
Assert.AreEqual(100, p1[0]);
Assert.AreEqual(200, p1[1]);
Assert.AreEqual(300, p1[2]);
}

Assert.AreEqual(100, array[0]);
Assert.AreEqual(200, array[1]);
Assert.AreEqual(300, array[2]);

float pThree = 0;
var refInt = 0;
obj.FuncPrimitivePtrToRef(ref refInt, null, ref pThree);
obj.FuncPrimitivePtrToRefWithDefVal(ref refInt, null, null, ref refInt);
obj.FuncPrimitivePtrToRefWithMultiOverload(ref refInt, null, null, ref refInt);
}
}
29 changes: 29 additions & 0 deletions tests/CSharpTemp/CSharpTemp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,3 +688,32 @@ HasOverrideOfHasPropertyWithDerivedType::HasOverrideOfHasPropertyWithDerivedType
void HasOverrideOfHasPropertyWithDerivedType::causeRenamingError()
{
}

void MultiOverloadPtrToRef::funcPrimitivePtrToRef(int* pOne, char* pTwo, float* pThree, bool* pFour)
{
}

void MultiOverloadPtrToRef::funcPrimitivePtrToRefWithDefVal(int* pOne, char* pTwo, Foo* pThree, int* pFour)
{
}

void MultiOverloadPtrToRef::funcPrimitivePtrToRefWithMultiOverload(int* pOne, char* pTwo, Foo* pThree, int* pFour, long* pFive)
{
}

MultiOverloadPtrToRef::MultiOverloadPtrToRef()
{
arr = new int[3]{0};
}

int* MultiOverloadPtrToRef::ReturnPrimTypePtr()
{
return arr;
}

void MultiOverloadPtrToRef::TakePrimTypePtr(int* ptr)
{
ptr[0] = 100;
ptr[1] = 200;
ptr[2] = 300;
}
13 changes: 13 additions & 0 deletions tests/CSharpTemp/CSharpTemp.h
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,16 @@ class DLL_API HasOverrideOfHasPropertyWithDerivedType : public HasPropertyWithDe
HasOverrideOfHasPropertyWithDerivedType();
virtual void causeRenamingError();
};

class DLL_API MultiOverloadPtrToRef
{
int * arr;
public:
void funcPrimitivePtrToRef(int *pOne, char* pTwo, float* pThree, bool* pFour = 0);
void funcPrimitivePtrToRefWithDefVal(int* pOne, char* pTwo, Foo* pThree, int* pFour = 0);
void funcPrimitivePtrToRefWithMultiOverload(int* pOne, char* pTwo, Foo* pThree, int* pFour = 0, long* pFive = 0);

MultiOverloadPtrToRef();
int* ReturnPrimTypePtr();
void TakePrimTypePtr(int* ptr);
};

0 comments on commit d45e2da

Please sign in to comment.