Add helper overload generation

Functions returning a value or array via an 'out' parameter will now get a convenience overload that returns the result via a return statement. In the case of arrays, only single-valued arrays will be supported. For example:

void GetIntegerv(enum pname, out int value)

will be get an overload of

int GetIntegerv(enum pname)

This will reduce the amount of helper overloads that must be maintained manually in GLHelpers.cs.
This commit is contained in:
thefiddler 2013-11-10 08:28:58 +01:00
parent 0d73706c88
commit d126d25215
4 changed files with 79 additions and 3 deletions

View file

@ -717,14 +717,39 @@ namespace Bind
}
}
if (f.ReturnType.WrapperType == WrapperTypes.ConvenienceReturnType ||
f.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType)
{
var r = f.ReturnType;
var p = f.WrappedDelegate.Parameters.Last();
f.Body.Add(String.Format("{0} {1};", GetDeclarationString(r), p.Name));
if (r.WrapperType == WrapperTypes.ConvenienceArrayReturnType)
{
var p_size = f.WrappedDelegate.Parameters[f.WrappedDelegate.Parameters.Count - 2];
f.Body.Add(String.Format("{0} = 1;", GetDeclarationString(p_size)));
}
fixed_statements.Add(String.Empty); // force the generation of an "unsafe" region
f.Body.Add(String.Format("{0}{2} {1}_ptr = {1};",
GetDeclarationString(r),
p.Name,
pointer_levels[p.IndirectionLevel]));
}
if (assign_statements.Count > 0)
{
// Call function
string callstring = GetInvocationString(f);
var callstring = GetInvocationString(f);
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)
{
var p = f.WrappedDelegate.Parameters.Last();
f.Body.Add(String.Format("{0};", callstring));
f.Body.Add(String.Format("retval = {0};", p.Name));
}
else if (func.ReturnType.CurrentType.ToLower().Contains("string"))
{
f.Body.Add(String.Format("{0} {1} = null; unsafe {{ {1} = new string((sbyte*){2}); }}",
@ -753,6 +778,13 @@ namespace Bind
{
f.Body.Add(String.Format("{0};", callstring));
}
else if (func.ReturnType.WrapperType == WrapperTypes.ConvenienceReturnType ||
func.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType)
{
var p = f.WrappedDelegate.Parameters.Last();
f.Body.Add(String.Format("{0};", callstring));
f.Body.Add(String.Format("return {0};", p.Name));
}
else if (func.ReturnType.CurrentType.ToLower().Contains("string"))
{
f.Body.Add(String.Format("unsafe {{ return new string((sbyte*){0}); }}",

View file

@ -102,10 +102,13 @@ namespace Bind
}
foreach (var overload in overload_list)
{
Utilities.Merge(delegates, overload);
delegates.Add(overload);
}
}
Console.WriteLine("Adding convenience overloads.");
delegates.AddRange(CreateConvenienceOverloads(delegates));
Console.WriteLine("Generating wrappers.");
var wrappers = CreateWrappers(delegates, enums);
@ -740,6 +743,45 @@ namespace Bind
}
}
IEnumerable<Delegate> CreateConvenienceOverloads(DelegateCollection delegates)
{
foreach (var list in delegates.Values)
{
var d = list.First();
if (d.Parameters.Count > 0)
{
var p = d.Parameters.Last();
var r = d.ReturnType;
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 &= r.CurrentType == "void" && r.Pointer == 0;
if (is_candidate)
{
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;
if (o.Parameters.Count > 0)
{
var p_size = o.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;
}
}
yield return o;
}
}
}
}
public IEnumerable<Function> WrapParameters(Function func, EnumCollection enums)
{
Function f;

View file

@ -283,11 +283,13 @@ namespace Bind
Settings.DefaultOutputNamespace = "OpenTK.Graphics.ES11";
break;
case "es2":
case "es20":
mode = GeneratorMode.ES20;
Settings.DefaultOutputNamespace = "OpenTK.Graphics.ES20";
break;
case "es3":
case "es30":
mode = GeneratorMode.ES30;
Settings.DefaultOutputNamespace = "OpenTK.Graphics.ES30";

View file

@ -83,7 +83,7 @@ namespace Bind
}
foreach (XPathNavigator nav in specs.CreateNavigator().Select(xpath_add))
{
Utilities.Merge(delegates, ReadDelegates(nav, apiversion));
delegates.AddRange(ReadDelegates(nav, apiversion));
}
}
}