Browse Source

Reworked support for out parameters in both backends and added a test.

pull/61/merge
triton 12 years ago
parent
commit
66ef3c55ff
  1. 19
      src/Generator/Generators/CLI/CLIMarshal.cs
  2. 33
      src/Generator/Generators/CLI/CLISourcesTemplate.cs
  3. 13
      src/Generator/Generators/CLI/CLITypePrinter.cs
  4. 24
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  5. 9
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  6. 16
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  7. 3
      src/Generator/Generators/Marshal.cs
  8. 1
      src/Generator/Types/ITypePrinter.cs
  9. 10
      tests/Basic/Basic.Tests.cs
  10. 6
      tests/Basic/Basic.cpp
  11. 1
      tests/Basic/Basic.cs
  12. 5
      tests/Basic/Basic.h

19
src/Generator/Generators/CLI/CLIMarshal.cs

@ -45,6 +45,13 @@ namespace CppSharp.Generators.CLI @@ -45,6 +45,13 @@ namespace CppSharp.Generators.CLI
{
var pointee = pointer.Pointee;
var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut))
{
Context.Return.Write(Context.ReturnVarName);
return true;
}
if (pointee.Desugar().IsPrimitiveType(PrimitiveType.Void))
{
Context.Return.Write("IntPtr({0})", Context.ReturnVarName);
@ -234,7 +241,11 @@ namespace CppSharp.Generators.CLI @@ -234,7 +241,11 @@ namespace CppSharp.Generators.CLI
public override bool VisitParameterDecl(Parameter parameter)
{
return parameter.Type.Visit(this, parameter.QualifiedType.Qualifiers);
Context.Parameter = parameter;
var ret = parameter.Type.Visit(this, parameter.QualifiedType.Qualifiers);
Context.Parameter = null;
return ret;
}
public override bool VisitTypedefDecl(TypedefDecl typedef)
@ -527,7 +538,8 @@ namespace CppSharp.Generators.CLI @@ -527,7 +538,8 @@ namespace CppSharp.Generators.CLI
public void MarshalValueClass(Class @class)
{
var marshalVar = "_marshal" + Context.ParameterIndex++;
var marshalVar = Context.MarshalVarPrefix + "_marshal" +
Context.ParameterIndex++;
Context.SupportBefore.WriteLine("auto {0} = ::{1}();", marshalVar,
@class.QualifiedOriginalName);
@ -572,7 +584,8 @@ namespace CppSharp.Generators.CLI @@ -572,7 +584,8 @@ namespace CppSharp.Generators.CLI
var marshalCtx = new MarshalContext(Context.Driver)
{
ArgName = fieldRef,
ParameterIndex = Context.ParameterIndex++
ParameterIndex = Context.ParameterIndex++,
MarshalVarPrefix = Context.MarshalVarPrefix
};
var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx);

33
src/Generator/Generators/CLI/CLISourcesTemplate.cs

@ -632,12 +632,14 @@ namespace CppSharp.Generators.CLI @@ -632,12 +632,14 @@ namespace CppSharp.Generators.CLI
{
var names = new List<string>();
var paramIndex = 0;
foreach (var param in method.Parameters)
{
var ctx = new MarshalContext(Driver)
{
Parameter = param,
ArgName = param.Name,
ParameterIndex = paramIndex++
};
var marshal = new CLIMarshalManagedToNativePrinter(ctx);
@ -729,7 +731,11 @@ namespace CppSharp.Generators.CLI @@ -729,7 +731,11 @@ namespace CppSharp.Generators.CLI
WriteLine("auto {0} = ::{1}();", valueMarshalName, @class.QualifiedOriginalName);
var param = new Parameter() { Name = "(*this)" };
var ctx = new MarshalContext(Driver) { Parameter = param };
var ctx = new MarshalContext(Driver)
{
MarshalVarPrefix = valueMarshalName,
Parameter = param
};
var marshal = new CLIMarshalManagedToNativePrinter(ctx);
marshal.MarshalValueClassFields(@class, valueMarshalName);
@ -860,6 +866,8 @@ namespace CppSharp.Generators.CLI @@ -860,6 +866,8 @@ namespace CppSharp.Generators.CLI
public struct ParamMarshal
{
public string Name;
public string Prefix;
public Parameter Param;
}
@ -881,18 +889,21 @@ namespace CppSharp.Generators.CLI @@ -881,18 +889,21 @@ namespace CppSharp.Generators.CLI
private ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex,
Function function = null)
{
var paramMarshal = new ParamMarshal { Name = param.Name, Param = param };
if (param.Type is BuiltinType)
{
return new ParamMarshal {Name = param.Name, Param = param};
}
return paramMarshal;
var argName = "arg" + paramIndex.ToString(CultureInfo.InvariantCulture);
if (param.Usage == ParameterUsage.Out)
if (param.IsOut || param.IsInOut)
{
var paramType = param.Type;
if (paramType.IsReference())
if (paramType is PointerType)
{
paramType = (paramType as PointerType).Pointee;
paramMarshal.Prefix = "&";
}
var typePrinter = new CppTypePrinter(Driver.TypeDatabase);
var type = paramType.Visit(typePrinter);
@ -923,12 +934,18 @@ namespace CppSharp.Generators.CLI @@ -923,12 +934,18 @@ namespace CppSharp.Generators.CLI
argName = marshal.ArgumentPrefix + argName;
}
return new ParamMarshal {Name = argName, Param = param};
paramMarshal.Name = argName;
return paramMarshal;
}
public void GenerateFunctionParams(List<ParamMarshal> @params)
{
var names = @params.Select(param => param.Name).ToList();
var names = @params.Select(param =>
{
if (!string.IsNullOrWhiteSpace(param.Prefix))
return param.Prefix + param.Name;
return param.Name;
}).ToList();
Write(string.Join(", ", names));
}

13
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -91,10 +91,11 @@ namespace CppSharp.Generators.CLI @@ -91,10 +91,11 @@ namespace CppSharp.Generators.CLI
public string VisitParameter(Parameter param, bool hasName = true)
{
Context.Parameter = param;
var type = param.Type.Visit(this, param.QualifiedType.Qualifiers);
var name = param.Name;
var str = "";
Context.Parameter = null;
var str = string.Empty;
if(param.Usage == ParameterUsage.Out)
str += "[System::Runtime::InteropServices::Out] ";
@ -104,8 +105,8 @@ namespace CppSharp.Generators.CLI @@ -104,8 +105,8 @@ namespace CppSharp.Generators.CLI
param.Usage == ParameterUsage.InOut)
str += "%";
if (hasName && !string.IsNullOrEmpty(name))
str += " " + name;
if (hasName && !string.IsNullOrEmpty(param.Name))
str += " " + param.Name;
return str;
}
@ -135,6 +136,10 @@ namespace CppSharp.Generators.CLI @@ -135,6 +136,10 @@ namespace CppSharp.Generators.CLI
PrimitiveType primitive;
if (pointee.Desugar().IsPrimitiveType(out primitive))
{
var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut))
return VisitPrimitiveType(primitive);
return "System::IntPtr";
}

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

@ -141,6 +141,13 @@ namespace CppSharp.Generators.CSharp @@ -141,6 +141,13 @@ namespace CppSharp.Generators.CSharp
PrimitiveType primitive;
if (pointee.Desugar().IsPrimitiveType(out primitive))
{
var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut))
{
Context.Return.Write("_{0}", param.Name);
return true;
}
Context.Return.Write(Context.ReturnVarName);
return true;
}
@ -410,7 +417,24 @@ namespace CppSharp.Generators.CSharp @@ -410,7 +417,24 @@ namespace CppSharp.Generators.CSharp
PrimitiveType primitive;
if (type.IsPrimitiveType(out primitive))
{
var param = Context.Parameter;
// From MSDN: "note that a ref or out parameter is classified as a moveable
// variable". This means we must create a local variable to hold the result
// and then assign this value to the parameter.
if (param.IsOut || param.IsInOut)
{
var typeName = Type.TypePrinterDelegate(type);
Context.SupportBefore.WriteLine("{0} _{1};", typeName,
Helpers.SafeIdentifier(param.Name));
Context.Return.Write("new global::System.IntPtr(&_{0})", param.Name);
}
else
Context.Return.Write(Context.Parameter.Name);
return true;
}

9
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -1813,13 +1813,13 @@ namespace CppSharp.Generators.CSharp @@ -1813,13 +1813,13 @@ namespace CppSharp.Generators.CSharp
foreach (var paramInfo in @params)
{
var param = paramInfo.Param;
if (param.Usage != ParameterUsage.Out && param.Usage != ParameterUsage.InOut)
continue;
if (!(param.IsOut || param.IsInOut)) continue;
var nativeVarName = paramInfo.Name;
var ctx = new CSharpMarshalContext(Driver)
{
Parameter = param,
ArgName = nativeVarName,
ReturnVarName = nativeVarName,
ReturnType = param.QualifiedType
@ -1890,7 +1890,7 @@ namespace CppSharp.Generators.CSharp @@ -1890,7 +1890,7 @@ namespace CppSharp.Generators.CSharp
var argName = "arg" + paramIndex.ToString(CultureInfo.InvariantCulture);
var paramMarshal = new ParamMarshal { Name = argName, Param = param };
if (param.Usage == ParameterUsage.Out)
if (param.IsOut || param.IsInOut)
{
var paramType = param.Type;
@ -1949,8 +1949,9 @@ namespace CppSharp.Generators.CSharp @@ -1949,8 +1949,9 @@ namespace CppSharp.Generators.CSharp
if (param.Kind == ParameterKind.IndirectReturnType)
continue;
var typeName = param.CSharpType(TypePrinter);
@params.Add(string.Format("{0}{1} {2}", GetParameterUsage(param.Usage),
param.Type, SafeIdentifier(param.Name)));
typeName, SafeIdentifier(param.Name)));
}
Write(string.Join(", ", @params));

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

@ -174,7 +174,13 @@ namespace CppSharp.Generators.CSharp @@ -174,7 +174,13 @@ namespace CppSharp.Generators.CSharp
PrimitiveType primitive;
if (pointee.Desugar().IsPrimitiveType(out primitive))
{
if (isManagedContext && Context.Parameter != null &&
(Context.Parameter.IsOut || Context.Parameter.IsInOut))
return VisitPrimitiveType(primitive, quals);
return "global::System.IntPtr";
}
Class @class;
if (pointee.IsTagDecl(out @class)
@ -365,7 +371,11 @@ namespace CppSharp.Generators.CSharp @@ -365,7 +371,11 @@ namespace CppSharp.Generators.CSharp
if (parameter.Kind == ParameterKind.IndirectReturnType)
return "global::System.IntPtr";
return paramType.Visit(this);
Context.Parameter = parameter;
var ret = paramType.Visit(this);
Context.Parameter = null;
return ret;
}
public CSharpTypePrinterResult VisitTypedefDecl(TypedefDecl typedef)
@ -439,8 +449,12 @@ namespace CppSharp.Generators.CSharp @@ -439,8 +449,12 @@ namespace CppSharp.Generators.CSharp
var args = new List<string>();
foreach (var param in @params)
{
Context.Parameter = param;
args.Add(VisitParameter(param, hasNames).Type);
}
Context.Parameter = null;
return string.Join(", ", args);
}

3
src/Generator/Generators/Marshal.cs

@ -9,6 +9,7 @@ namespace CppSharp.Generators @@ -9,6 +9,7 @@ namespace CppSharp.Generators
Driver = driver;
SupportBefore = new TextGenerator();
Return = new TextGenerator();
MarshalVarPrefix = string.Empty;
}
public Driver Driver { get; private set; }
@ -28,6 +29,8 @@ namespace CppSharp.Generators @@ -28,6 +29,8 @@ namespace CppSharp.Generators
public Parameter Parameter { get; set; }
public int ParameterIndex { get; set; }
public Function Function { get; set; }
public string MarshalVarPrefix { get; set; }
}
public abstract class MarshalPrinter : AstVisitor

1
src/Generator/Types/ITypePrinter.cs

@ -47,6 +47,7 @@ namespace CppSharp.Types @@ -47,6 +47,7 @@ namespace CppSharp.Types
public TypePrinterContextKind Kind;
public Declaration Declaration;
public Parameter Parameter;
public Type Type;
}

10
tests/Basic/Basic.Tests.cs

@ -44,6 +44,16 @@ public class BasicTests @@ -44,6 +44,16 @@ public class BasicTests
Assert.That(hello.RetEnum(Enum.F), Is.EqualTo(-9));
}
[Test]
public void TestPrimitiveOutParameters()
{
var hello = new Hello();
float f;
Assert.That(hello.TestPrimitiveOut(out f), Is.True);
Assert.That(f, Is.EqualTo(10.0f));
}
[Test]
public void TestNullRef()
{

6
tests/Basic/Basic.cpp

@ -95,6 +95,12 @@ Hello* Hello::RetNull() @@ -95,6 +95,12 @@ Hello* Hello::RetNull()
return 0;
}
bool Hello::TestPrimitiveOut(CS_OUT float* f)
{
*f = 10;
return true;
}
int unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int))
{
return ret.A;

1
tests/Basic/Basic.cs

@ -15,6 +15,7 @@ namespace CppSharp.Tests @@ -15,6 +15,7 @@ namespace CppSharp.Tests
{
lib.SetClassAsValueType("Bar");
lib.SetClassAsValueType("Bar2");
lib.SetMethodParameterUsage("Hello", "TestPrimitiveOut", 1, ParameterUsage.Out);
}
static class Program

5
tests/Basic/Basic.h

@ -4,6 +4,8 @@ @@ -4,6 +4,8 @@
#define DLL_API
#endif
#define CS_OUT
class DLL_API Foo
{
public:
@ -84,6 +86,9 @@ public: @@ -84,6 +86,9 @@ public:
int RetEnum(Enum);
Hello* RetNull();
bool TestPrimitiveOut(CS_OUT float* f);
};
class DLL_API AbstractFoo

Loading…
Cancel
Save