Added WrapperTypes.ConvenienceArrayType

These are convenience parameters for function receiving a size and an
array parameter, like DeleteTextures(int n, int[] ids). The generator
will now add overloads taking a single parameter, such as
DeleteTexture(int id).
This commit is contained in:
Stefanos A. 2013-11-10 18:29:53 +01:00
parent 8003d06315
commit 293c020151
3 changed files with 104 additions and 34 deletions

View file

@ -627,9 +627,6 @@ namespace Bind
"{0} = ({1}){0}_ptr.Target;",
p.Name, p.QualifiedType));
}
// Note! The following line modifies f.Parameters, *not* this.Parameters
p.Name = "(IntPtr)" + p.Name + "_ptr.AddrOfPinnedObject()";
}
else if (p.WrapperType == WrapperTypes.PointerParameter ||
p.WrapperType == WrapperTypes.ArrayParameter ||
@ -649,8 +646,10 @@ namespace Bind
{
assign_statements.Add(String.Format("{0} = *{0}_ptr;", p.Name));
}
p.Name = p.Name + "_ptr";
}
else if (p.WrapperType == WrapperTypes.None)
{
// do nothing
}
else
{
@ -659,6 +658,18 @@ namespace Bind
p.WrapperType));
}
}
else if (p.WrapperType == WrapperTypes.ConvenienceArrayType)
{
var p_array = f.WrappedDelegate.Parameters[f.WrappedDelegate.Parameters.Count - 1];
var p_size = f.WrappedDelegate.Parameters[f.WrappedDelegate.Parameters.Count - 2];
declaration_statements.Add(String.Format(
"const {0} = 1;",
GetDeclarationString(p_size, false)));
declaration_statements.Add(String.Format("{0}_ptr = ({1})&{2};",
GetDeclarationString(p_array, false),
GetDeclarationString(p_array as Type),
p.Name));
}
p.QualifiedType = f.WrappedDelegate.Parameters[index].QualifiedType;
}
@ -676,7 +687,7 @@ namespace Bind
GetDeclarationString(p_size, false)));
}
declaration_statements.Add(String.Format("{0} retval;", GetDeclarationString(r)));
declaration_statements.Add(String.Format("{0}{2} {1} = &retval;",
declaration_statements.Add(String.Format("{0}{2} {1}_ptr = &retval;",
GetDeclarationString(r),
p.Name,
pointer_levels[p.IndirectionLevel]));
@ -753,16 +764,22 @@ namespace Bind
{
// Call function
var callstring = GetInvocationString(f);
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
if (func.Parameters.Any(p => p.WrapperType == WrapperTypes.ConvenienceArrayType))
{
// foo(int id) { foo(1, ref id) }
callstring = GetInvocationString(f.WrappedDelegate);
f.Body.Add(String.Format("{0}{1};",
f.ReturnType.CurrentType.ToLower().Contains("void") ? String.Empty : "return ",
callstring));
}
else if (f.ReturnType.CurrentType.ToLower().Contains("void"))
{
f.Body.Add(String.Format("{0};", callstring));
}
else if (func.ReturnType.WrapperType == WrapperTypes.ConvenienceReturnType ||
func.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType)
{
// The wrapper has completely different parameters,
// we need to build the invocation string via the wrapped
// delegate instead.
// int foo() { int value; foo(1, &value); retval = value }
callstring = GetInvocationString(f.WrappedDelegate);
var p = f.WrappedDelegate.Parameters.Last();
f.Body.Add(String.Format("{0};", callstring));
@ -795,16 +812,22 @@ namespace Bind
{
// Call function and return
var callstring = GetInvocationString(f);
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
if (func.Parameters.Any(p => p.WrapperType == WrapperTypes.ConvenienceArrayType))
{
// int foo(int id) { return foo(1, ref id) }
callstring = GetInvocationString(f.WrappedDelegate);
f.Body.Add(String.Format("{0}{1};",
f.ReturnType.CurrentType.ToLower().Contains("void") ? String.Empty : "return ",
callstring));
}
else if (f.ReturnType.CurrentType.ToLower().Contains("void"))
{
f.Body.Add(String.Format("{0};", callstring));
}
else if (func.ReturnType.WrapperType == WrapperTypes.ConvenienceReturnType ||
func.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType)
{
// The wrapper has completely different parameters,
// we need to build the invocation string via the wrapped
// delegate instead.
// int foo() { int retval; foo(1, &retval); return retval }
callstring = GetInvocationString(f.WrappedDelegate);
var p = f.WrappedDelegate.Parameters.Last();
f.Body.Add(String.Format("{0};", callstring));
@ -1103,7 +1126,32 @@ namespace Bind
}
}
sb.Append(p.Name);
switch (p.WrapperType)
{
case WrapperTypes.GenericParameter:
if (p.Generic)
{
sb.Append("(IntPtr)");
sb.Append(p.Name);
sb.Append("_ptr.AddrOfPinnedObject()");
}
else
{
sb.Append(p.Name);
}
break;
case WrapperTypes.ArrayParameter:
case WrapperTypes.ReferenceParameter:
sb.Append(p.Name);
sb.Append("_ptr");
break;
default:
sb.Append(p.Name);
break;
}
if (p.Unchecked)
sb.Append(")");

View file

@ -106,13 +106,13 @@ namespace Bind
}
}
Console.WriteLine("Adding convenience overloads.");
Console.WriteLine("Generating convenience overloads.");
delegates.AddRange(CreateConvenienceOverloads(delegates));
Console.WriteLine("Generating wrappers.");
var wrappers = CreateWrappers(delegates, enums);
Console.WriteLine("Creating CLS compliant overloads.");
Console.WriteLine("Generating CLS compliant overloads.");
wrappers = CreateCLSCompliantWrappers(wrappers, enums);
Console.WriteLine("Removing non-CLS compliant duplicates.");
@ -361,7 +361,8 @@ namespace Bind
// If we have a convenience overload, we should turn the name from
// plural into singular
if (d.ReturnType.WrapperType == WrapperTypes.ConvenienceReturnType ||
d.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType)
d.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType ||
d.Parameters.Any(p => p.WrapperType == WrapperTypes.ConvenienceArrayType))
{
trimmed_name = trimmed_name.Replace("Queries", "Query");
trimmed_name = trimmed_name.TrimEnd('s');
@ -772,28 +773,42 @@ namespace Bind
bool is_candidate = true;
is_candidate &= d.Name.EndsWith("v") || d.Name.EndsWith("s");
is_candidate &= p.Pointer > 0 && p.Flow == FlowDirection.Out;
is_candidate &= p.Pointer > 0;
is_candidate &= r.CurrentType == "void" && r.Pointer == 0;
if (is_candidate)
if (is_candidate && p.Flow == FlowDirection.Out)
{
var o = new Delegate(d);
o.ReturnType = new Type(o.Parameters.Last());
o.ReturnType.Pointer = 0;
o.Parameters.RemoveAt(o.Parameters.Count - 1);
o.ReturnType.WrapperType = WrapperTypes.ConvenienceReturnType;
var f = new Delegate(d);
f.ReturnType = new Type(f.Parameters.Last());
f.ReturnType.Pointer = 0;
f.Parameters.RemoveAt(f.Parameters.Count - 1);
f.ReturnType.WrapperType = WrapperTypes.ConvenienceReturnType;
if (o.Parameters.Count > 0)
if (f.Parameters.Count > 0)
{
var p_size = o.Parameters.Last();
var p_size = f.Parameters.Last();
if (p_size.CurrentType.ToLower().Contains("int") && p_size.Pointer == 0)
{
o.Parameters.RemoveAt(o.Parameters.Count - 1);
o.ReturnType.WrapperType = WrapperTypes.ConvenienceArrayReturnType;
f.Parameters.RemoveAt(f.Parameters.Count - 1);
f.ReturnType.WrapperType = WrapperTypes.ConvenienceArrayReturnType;
}
}
yield return o;
yield return f;
}
else if (is_candidate && p.Flow != FlowDirection.Out)
{
if (d.Parameters.Count == 2)
{
var f = new Delegate(d);
var p_array = f.Parameters.Last();
var p_size = f.Parameters[f.Parameters.Count - 2];
f.Parameters.RemoveAt(f.Parameters.Count - 2);
p_array.WrapperType = WrapperTypes.ConvenienceArrayType;
p_array.Pointer = 0;
yield return f;
}
}
}
}
@ -824,6 +839,7 @@ namespace Bind
p.Reference = true;
p.Array--;
p.Pointer--;
p.WrapperType = WrapperTypes.ReferenceParameter;
}
}
}
@ -841,6 +857,7 @@ namespace Bind
p.Reference = true;
p.Array--;
p.Pointer--;
p.WrapperType = WrapperTypes.ReferenceParameter;
}
}
f = new Function(_this);
@ -857,8 +874,7 @@ namespace Bind
if (p.WrapperType == WrapperTypes.ArrayParameter)
{
p.Reference = false;
//p.Array--;
//p.Pointer++;
p.WrapperType = WrapperTypes.PointerParameter;
}
}
f = new Function(_this);

View file

@ -66,15 +66,21 @@ namespace Bind
/// <summary>
/// Function normally returns a value via an out parameter.
/// This overload returns a single item directly.
/// e.g. void GetIntegerv(enum, out int) => int GetInteger(enum)
/// e.g. void GetIntegerv(enum pname, out int value) => int GetInteger(enum pname)
/// </summary>
ConvenienceReturnType,
/// <summary>
/// Function normally returns an array via an out parameter.
/// This overload returns a single item directly.
/// e.g. void GenBuffers(int n, int[]) => int GenBuffer()
/// e.g. void GenBuffers(int count, int[] ids) => int GenBuffer()
/// </summary>
ConvenienceArrayReturnType,
/// <summary>
/// Function normally takes an array in parameter.
/// This overload takes a single item directly.
/// e.g. void DeleteBuffers(int count, int[] ids) => DeleteBuffer(int id)
/// </summary>
ConvenienceArrayType,
}
#endregion