2006-10-08 18:26:43 +00:00
|
|
|
#region License
|
|
|
|
//Copyright (c) 2006 Stephen Apostolopoulos
|
|
|
|
//See license.txt for license info
|
|
|
|
#endregion
|
2006-09-28 22:07:53 +00:00
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
|
|
using System.Collections;
|
|
|
|
|
|
|
|
namespace OpenTK.OpenGL.Bind
|
|
|
|
{
|
2006-10-08 18:26:43 +00:00
|
|
|
#region WrapperTypes enum
|
2006-10-15 20:28:57 +00:00
|
|
|
|
2006-09-30 18:24:41 +00:00
|
|
|
public enum WrapperTypes
|
|
|
|
{
|
|
|
|
None,
|
2006-10-15 20:28:57 +00:00
|
|
|
VoidArray,
|
2006-10-10 19:34:44 +00:00
|
|
|
Array,
|
2006-10-15 20:28:57 +00:00
|
|
|
UncheckedParameter,
|
2006-09-30 18:24:41 +00:00
|
|
|
ReturnsString,
|
|
|
|
ReturnsVoidPointer,
|
|
|
|
}
|
2006-10-15 20:28:57 +00:00
|
|
|
|
2006-10-08 18:26:43 +00:00
|
|
|
#endregion
|
2006-09-30 18:24:41 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
static class Translation
|
|
|
|
{
|
|
|
|
public static char[] Separators = { ' ', '\n', ',', '(', ')', ';', '#' };
|
|
|
|
|
|
|
|
#region Dictionaries
|
|
|
|
|
|
|
|
static Dictionary<string, string> parameter_names = new Dictionary<string, string>();
|
|
|
|
|
2006-10-10 23:40:36 +00:00
|
|
|
#region GL types dictionary
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
private static Dictionary<string, string> _gl_types;
|
2006-10-10 23:40:36 +00:00
|
|
|
|
|
|
|
public static Dictionary<string, string> GLTypes
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
|
|
|
get { return Translation._gl_types; }
|
|
|
|
set { Translation._gl_types = value; }
|
|
|
|
}
|
|
|
|
|
2006-10-10 23:40:36 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region CS types dictionary
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
private static Dictionary<string, string> _cs_types;
|
|
|
|
|
2006-10-10 23:40:36 +00:00
|
|
|
public static Dictionary<string, string> CSTypes
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
|
|
|
get { return Translation._cs_types; }
|
|
|
|
set { Translation._cs_types = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2006-10-10 23:40:36 +00:00
|
|
|
#region GLX types dictionary
|
|
|
|
|
|
|
|
private static Dictionary<string, string> _glx_types;
|
|
|
|
|
|
|
|
public static Dictionary<string, string> GLXTypes
|
|
|
|
{
|
|
|
|
get { return _glx_types; }
|
|
|
|
set { _glx_types = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region WGL types dictionary
|
|
|
|
|
|
|
|
private static Dictionary<string, string> _wgl_types;
|
|
|
|
|
|
|
|
public static Dictionary<string, string> WGLTypes
|
|
|
|
{
|
|
|
|
get { return _wgl_types; }
|
|
|
|
set { _wgl_types = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
#region Constructor
|
|
|
|
|
|
|
|
static Translation()
|
|
|
|
{
|
|
|
|
// Names
|
|
|
|
parameter_names.Add("base", "@base");
|
|
|
|
parameter_names.Add("object", "@object");
|
|
|
|
parameter_names.Add("string", "@string");
|
|
|
|
parameter_names.Add("ref", "reference");
|
|
|
|
parameter_names.Add("params", "parameters");
|
|
|
|
parameter_names.Add("in", "@in");
|
2006-10-10 23:40:36 +00:00
|
|
|
parameter_names.Add("class", "@class");
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
#region Translate enums
|
2006-09-28 22:07:53 +00:00
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
public static void TranslateEnums(System.Collections.Hashtable enums)
|
|
|
|
{
|
2006-10-11 21:42:22 +00:00
|
|
|
// Add missing enums.
|
|
|
|
{
|
|
|
|
Enum e = new Enum();
|
|
|
|
Constant c;
|
|
|
|
e.Name = "SGIX_icc_texture";
|
|
|
|
c = new Constant("RGB_ICC_SGIX", "0x8460"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("RGBA_ICC_SGIX", "0x8461"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("ALPHA_ICC_SGIX", "0x8462"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("LUMINANCE_ICC_SGIX", "0x8463"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("INTENSITY_ICC_SGIX", "0x8464"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("LUMINANCE_ALPHA_ICC_SGIX", "0x8465"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("R5_G6_B5_ICC_SGIX", "0x8466"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("R5_G6_B5_A8_ICC_SGIX", "0x8467"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("ALPHA16_ICC_SGIX", "0x8468"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("LUMINANCE16_ICC_SGIX", "0x8469"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("INTENSITY16_ICC_SGIX", "0x846A"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
c = new Constant("LUMINANCE16_ALPHA8_ICC_SGIX", "0x846B"); e.ConstantCollection.Add(c.Name, c);
|
|
|
|
|
|
|
|
enums.Add(e.Name, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Translate enums.
|
2006-10-10 19:34:44 +00:00
|
|
|
foreach (Enum e in enums.Values)
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
if (Char.IsDigit(e.Name[0]))
|
|
|
|
e.Name = e.Name.Insert(0, "_");
|
|
|
|
|
|
|
|
if (e.Name == "Boolean")
|
|
|
|
continue;
|
|
|
|
|
|
|
|
foreach (Constant c in e.ConstantCollection.Values)
|
|
|
|
{
|
2006-10-11 21:42:22 +00:00
|
|
|
// Prepend an '_' if the first letter is a number (e.g. 4_BYTES -> _4_BYTES)
|
2006-10-10 19:34:44 +00:00
|
|
|
if (Char.IsDigit(c.Name[0]))
|
|
|
|
c.Name = c.Name.Insert(0, "_");
|
|
|
|
|
2006-10-11 21:42:22 +00:00
|
|
|
// Prepend an '_' to the aliased value, if it starts with a number (e.g. DataType.4_BYTES -> DataType._4_BYTES)
|
2006-10-10 19:34:44 +00:00
|
|
|
if (c.Value.Contains(".") && Char.IsDigit(c.Value[c.Value.IndexOf('.') + 1]))
|
|
|
|
c.Value = c.Value.Insert(c.Value.IndexOf('.') + 1, "_");
|
2006-10-11 21:42:22 +00:00
|
|
|
|
|
|
|
// There are cases when a value is not a number but an aliased constant, with no enum specified.
|
|
|
|
// In this case try searching all enums for the correct constant to alias (stupid opengl group).
|
|
|
|
if (!c.Value.Contains(".") && !c.Value.StartsWith("0x") && !Char.IsDigit(c.Value[0]))
|
|
|
|
{
|
|
|
|
if (c.Value.StartsWith("GL_"))
|
|
|
|
c.Value = c.Value.TrimStart('G', 'L', '_');
|
|
|
|
|
|
|
|
if (Char.IsDigit(c.Value[0]))
|
|
|
|
c.Value = c.Value.Insert(0, "_");
|
|
|
|
|
|
|
|
foreach (Enum search_enum in enums.Values)
|
|
|
|
foreach (Constant search_constant in search_enum.ConstantCollection.Values)
|
|
|
|
if (search_constant.Name == c.Value || search_constant.Name == c.Value.TrimStart('_'))
|
|
|
|
c.Value = c.Value.Insert(0, search_enum.Name + ".");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle enum.spec bugs:
|
|
|
|
if (c.Value.Contains("LightProperty"))
|
|
|
|
c.Value = c.Value.Replace("LightProperty", "LightParameter");
|
2006-10-10 19:34:44 +00:00
|
|
|
}
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-11 21:42:22 +00:00
|
|
|
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Translate functions
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
public static void TranslateFunctions(List<Function> functions, Hashtable enums, out List<Function> wrappers)
|
|
|
|
{
|
|
|
|
foreach (Function f in functions)
|
|
|
|
{
|
|
|
|
TranslateReturnValue(f, enums);
|
|
|
|
TranslateParameters(f, enums);
|
|
|
|
|
|
|
|
if (f.NeedsWrapper)
|
|
|
|
f.Name = f.Name + "_";
|
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
|
|
|
|
wrappers = GenerateWrappers(functions);
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
2006-09-30 18:24:41 +00:00
|
|
|
#region Translate return value
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
private static void TranslateReturnValue(Function f, Hashtable enums)
|
|
|
|
{
|
|
|
|
string s;
|
|
|
|
|
|
|
|
if (f.ReturnValue == "void")
|
|
|
|
return;
|
|
|
|
|
2006-10-10 23:40:36 +00:00
|
|
|
if (GLTypes.TryGetValue(f.ReturnValue, out s))
|
2006-09-28 22:07:53 +00:00
|
|
|
f.ReturnValue = s;
|
|
|
|
|
|
|
|
if (f.ReturnValue == "void[]")
|
|
|
|
{
|
2006-09-30 18:24:41 +00:00
|
|
|
f.NeedsWrapper = true;
|
|
|
|
f.WrapperType = WrapperTypes.ReturnsVoidPointer;
|
2006-09-28 22:07:53 +00:00
|
|
|
f.ReturnValue = "IntPtr";
|
|
|
|
}
|
|
|
|
|
2006-09-30 18:24:41 +00:00
|
|
|
if (f.ReturnValue == "GLstring")
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
|
|
|
f.NeedsWrapper = true;
|
2006-09-30 18:24:41 +00:00
|
|
|
f.WrapperType = WrapperTypes.ReturnsString;
|
|
|
|
f.ReturnValue = "IntPtr";
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-30 18:24:41 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
#endregion
|
|
|
|
|
2006-09-30 18:24:41 +00:00
|
|
|
#region Translate parameters
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
private static void TranslateParameters(Function f, Hashtable enums)
|
|
|
|
{
|
|
|
|
string s;
|
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
foreach (Parameter p in f.Parameters) // Translate each parameter of the function, and check for needed wrappers.
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-15 20:28:57 +00:00
|
|
|
#region Translate parameter name
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
if (parameter_names.TryGetValue(p.Name, out s))
|
|
|
|
p.Name = s;
|
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
#endregion
|
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
#region Translate parameter type
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
//if (p.Type.Contains("Boolean"))
|
|
|
|
//{
|
|
|
|
// p.Type = "GLboolean";
|
|
|
|
//}
|
|
|
|
if (enums.ContainsKey(p.Type))
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
|
|
|
p.Type = "Enums." + p.Type;
|
|
|
|
}
|
2006-09-30 19:58:51 +00:00
|
|
|
else if (p.Type == "GLenum")
|
|
|
|
{
|
2006-10-08 18:26:43 +00:00
|
|
|
if (enums.ContainsKey(f.Category))
|
|
|
|
p.Type = "Enums." + f.Category;
|
2006-09-30 19:58:51 +00:00
|
|
|
}
|
2006-10-10 23:40:36 +00:00
|
|
|
else if (GLTypes.TryGetValue(p.Type, out s))
|
2006-09-28 22:07:53 +00:00
|
|
|
p.Type = s;
|
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
#endregion
|
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
#region Check for needed wrappers
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
if (p.Type.Contains("ushort") && f.Name.Contains("LineStipple")) // glLineStipple needs wrapper to allow for unchecked mask values.
|
2006-09-30 18:24:41 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
p.NeedsWrapper = true;
|
2006-10-15 20:28:57 +00:00
|
|
|
p.WrapperType = WrapperTypes.UncheckedParameter;
|
2006-10-10 19:34:44 +00:00
|
|
|
p.Unchecked = true;
|
2006-09-30 18:24:41 +00:00
|
|
|
}
|
2006-10-15 20:28:57 +00:00
|
|
|
else if (p.Array && p.Type.Contains("string")) // string parameters do not need special wrappers.
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
p.NeedsWrapper = false;
|
|
|
|
p.WrapperType = WrapperTypes.None;
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-15 20:28:57 +00:00
|
|
|
else if (p.Array && p.Type.Contains("char")) // GLchar[] parameters should become (in) string or (out) StringBuilder
|
2006-10-09 23:58:30 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
if (p.Flow == Parameter.FlowDirection.Out)
|
|
|
|
p.Type = "StringBuilder";
|
2006-10-15 20:28:57 +00:00
|
|
|
else
|
2006-10-10 19:34:44 +00:00
|
|
|
p.Type = "string";
|
2006-10-09 23:58:30 +00:00
|
|
|
p.Array = false;
|
|
|
|
}
|
2006-10-15 20:28:57 +00:00
|
|
|
else if (p.Array) // All other array parameters need wrappers (around IntPtr).
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
p.NeedsWrapper = true;
|
|
|
|
|
|
|
|
if (p.Type.Contains("void"))
|
2006-10-15 20:28:57 +00:00
|
|
|
p.WrapperType = WrapperTypes.VoidArray;
|
2006-10-10 19:34:44 +00:00
|
|
|
else
|
|
|
|
p.WrapperType = WrapperTypes.Array;
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
p.Type = "IntPtr";
|
2006-10-15 20:28:57 +00:00
|
|
|
p.Array = false; // We do not want an array of IntPtrs (IntPtr[]) - it is the IntPtr that points to the array.
|
|
|
|
p.Flow = Parameter.FlowDirection.Undefined; // The same wrapper works for either in or out parameters.
|
2006-09-30 18:24:41 +00:00
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-10-15 20:28:57 +00:00
|
|
|
if (p.NeedsWrapper) // If there is at least 1 parameter that needs wrappers, mark the funcction for wrapping.
|
2006-09-30 18:24:41 +00:00
|
|
|
{
|
2006-09-28 22:07:53 +00:00
|
|
|
f.NeedsWrapper = true;
|
2006-10-10 19:34:44 +00:00
|
|
|
f.WrapperType = p.WrapperType;
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
|
|
|
|
#endregion
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
#endregion
|
|
|
|
|
2006-09-30 18:24:41 +00:00
|
|
|
#region Generate wrappers
|
2006-10-10 19:34:44 +00:00
|
|
|
|
|
|
|
private static List<Function> GenerateWrappers(List<Function> functions)
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
List<Function> wrappers = new List<Function>();
|
|
|
|
Function w;
|
2006-09-28 22:07:53 +00:00
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
foreach (Function f in functions)
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
if (f.NeedsWrapper)
|
|
|
|
{
|
2006-10-15 20:28:57 +00:00
|
|
|
if (f.WrapperType == WrapperTypes.UncheckedParameter)
|
2006-10-10 19:34:44 +00:00
|
|
|
{
|
|
|
|
w = new Function(f);
|
|
|
|
w.Name = w.Name.TrimEnd('_');
|
|
|
|
|
|
|
|
// Search and replace ushort parameters with ints.
|
|
|
|
Predicate<Parameter> is_ushort_parameter = new Predicate<Parameter>(delegate(Parameter p) { return p.Type == "GLushort"; });
|
|
|
|
Parameter oldp = w.Parameters.Find(is_ushort_parameter);
|
|
|
|
Parameter newp = new Parameter(oldp);
|
|
|
|
newp.Type = "GLint";
|
|
|
|
w.Parameters = w.Parameters.ReplaceAll(oldp, newp);
|
|
|
|
|
|
|
|
// Call the low-level function wrapping (all parameters marked with Unchecked will automatically
|
|
|
|
// be decorated with the unchecked keyword).
|
|
|
|
w.Body.Add((f.ReturnValue.Contains("void") ? "" : "return ") + f.CallString() + ";");
|
|
|
|
|
|
|
|
// Add the wrapper.
|
|
|
|
wrappers.Add(w);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f.WrapperType == WrapperTypes.ReturnsString)
|
|
|
|
{
|
|
|
|
w = new Function(f);
|
|
|
|
w.Name = w.Name.TrimEnd('_');
|
|
|
|
|
|
|
|
// Replace the IntPtr return value with string.
|
|
|
|
w.ReturnValue = "string";
|
|
|
|
|
|
|
|
// Wrap the call to the low-level function (marshal the IntPtr to string).
|
|
|
|
w.Body.Add("return Marshal.PtrToStringAnsi(" + f.CallString() + ");");
|
|
|
|
|
|
|
|
// Add the wrapper.
|
|
|
|
wrappers.Add(w);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
//if (
|
|
|
|
WrapPointers(f, wrappers);
|
|
|
|
count = 0;
|
|
|
|
}
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
return wrappers;
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
static int count = 0;
|
|
|
|
private static void WrapPointers(Function f, List<Function> wrappers)
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
if (count == 0)
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
wrappers.Add(IntPtrToIntPtr(f));
|
|
|
|
}
|
2006-09-28 22:07:53 +00:00
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
if (count >= 0 && count < f.Parameters.Count)
|
|
|
|
{
|
|
|
|
if (f.Parameters[count].NeedsWrapper)
|
2006-09-28 22:07:53 +00:00
|
|
|
{
|
2006-10-10 19:34:44 +00:00
|
|
|
++count;
|
|
|
|
WrapPointers(f, wrappers);
|
|
|
|
--count;
|
|
|
|
|
|
|
|
Function w = IntPtrToObject(f, count);
|
|
|
|
wrappers.Add(w);
|
|
|
|
|
|
|
|
++count;
|
|
|
|
WrapPointers(w, wrappers);
|
|
|
|
--count;
|
|
|
|
|
|
|
|
if (f.Parameters[count].WrapperType == WrapperTypes.Array)
|
|
|
|
{
|
|
|
|
w = IntPtrToArray(f, count);
|
|
|
|
wrappers.Add(w);
|
|
|
|
|
|
|
|
++count;
|
|
|
|
WrapPointers(w, wrappers);
|
|
|
|
--count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++count;
|
|
|
|
WrapPointers(f, wrappers);
|
|
|
|
--count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-09-28 22:07:53 +00:00
|
|
|
|
2006-10-10 19:34:44 +00:00
|
|
|
// IntPtr -> IntPtr wrapper.
|
|
|
|
private static Function IntPtrToIntPtr(Function f)
|
|
|
|
{
|
|
|
|
Function w = new Function(f);
|
|
|
|
w.Name = w.Name.TrimEnd('_');
|
|
|
|
|
|
|
|
w.Body.Add((f.ReturnValue.Contains("void") ? "" : "return ") + f.CallString() + ";");
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IntPtr -> object wrapper.
|
|
|
|
private static Function IntPtrToObject(Function f, int index)
|
|
|
|
{
|
|
|
|
Function w = new Function(f);
|
|
|
|
w.Name = w.Name.TrimEnd('_');
|
|
|
|
|
|
|
|
Parameter newp = new Parameter(f.Parameters[index]);
|
|
|
|
newp.Type = "object";
|
|
|
|
if (newp.Flow == Parameter.FlowDirection.Out)
|
|
|
|
newp.Flow = Parameter.FlowDirection.Undefined;
|
|
|
|
w.Parameters = w.Parameters.Replace(f.Parameters[index], newp);
|
|
|
|
|
|
|
|
// In the function body we should pin all objects in memory before calling the
|
|
|
|
// low-level function.
|
|
|
|
w.Body = GenerateBodyForPins(w);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IntPtr -> GL[...] wrapper.
|
|
|
|
private static Function IntPtrToArray(Function f, int index)
|
|
|
|
{
|
|
|
|
Function w = new Function(f);
|
|
|
|
w.Name = w.Name.TrimEnd('_');
|
|
|
|
|
|
|
|
// Search and replace IntPtr parameters with the know parameter types:
|
|
|
|
Parameter newp = new Parameter(f.Parameters[index]);
|
|
|
|
newp.Type = f.Parameters[index].PreviousType;
|
|
|
|
newp.Array = true;
|
|
|
|
w.Parameters = w.Parameters.Replace(f.Parameters[index], newp);
|
|
|
|
|
|
|
|
// In the function body we should pin all objects in memory before calling the
|
|
|
|
// low-level function.
|
|
|
|
w.Body = GenerateBodyForPins(w);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static FunctionBody GenerateBodyForPins(Function w)
|
|
|
|
{
|
|
|
|
|
|
|
|
FunctionBody body = new FunctionBody();
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.Append("(");
|
|
|
|
foreach (Parameter p in w.Parameters)
|
|
|
|
{
|
|
|
|
if (p.Type == "object" || p.Array && !p.Type.Contains("string")) // we should allow the default marshalling behavior for strings.
|
|
|
|
{
|
|
|
|
body.Add("GCHandle h" + i + " = GCHandle.Alloc(" + p.Name + ", GCHandleType.Pinned);");
|
|
|
|
sb.Append("h" + i + ".AddrOfPinnedObject()" + ", ");
|
|
|
|
i++;
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
sb.Append(p.Name + ", ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sb.Replace(", ", ")", sb.Length - 2, 2);
|
|
|
|
|
|
|
|
body.Add("try");
|
|
|
|
body.Add("{");
|
|
|
|
body.Add(
|
|
|
|
" " +
|
|
|
|
(w.ReturnValue.Contains("void") ? "" : "return ") +
|
|
|
|
w.Name + "_" +
|
|
|
|
sb.ToString() +
|
|
|
|
";");
|
|
|
|
body.Add("}");
|
|
|
|
body.Add("finally");
|
|
|
|
body.Add("{");
|
|
|
|
while (i > 0)
|
|
|
|
{
|
|
|
|
body.Add(" h" + --i + ".Free();");
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
body.Add("}");
|
|
|
|
|
|
|
|
return body;
|
2006-09-28 22:07:53 +00:00
|
|
|
}
|
2006-10-10 19:34:44 +00:00
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2006-09-28 22:07:53 +00:00
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|