diff --git a/Source/Bind/CSharpSpecWriter.cs b/Source/Bind/CSharpSpecWriter.cs index a8c6112a..f7964b50 100644 --- a/Source/Bind/CSharpSpecWriter.cs +++ b/Source/Bind/CSharpSpecWriter.cs @@ -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}); }}", diff --git a/Source/Bind/FuncProcessor.cs b/Source/Bind/FuncProcessor.cs index faa2bf72..f0d304d9 100644 --- a/Source/Bind/FuncProcessor.cs +++ b/Source/Bind/FuncProcessor.cs @@ -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 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 WrapParameters(Function func, EnumCollection enums) { Function f; diff --git a/Source/Bind/Main.cs b/Source/Bind/Main.cs index be8ea0f4..c72a592c 100644 --- a/Source/Bind/Main.cs +++ b/Source/Bind/Main.cs @@ -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"; diff --git a/Source/Bind/XmlSpecReader.cs b/Source/Bind/XmlSpecReader.cs index e6128735..272022c3 100644 --- a/Source/Bind/XmlSpecReader.cs +++ b/Source/Bind/XmlSpecReader.cs @@ -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)); } } }