diff --git a/generator/Makefile.am b/generator/Makefile.am index 2fc3aabe7..a45405357 100644 --- a/generator/Makefile.am +++ b/generator/Makefile.am @@ -64,6 +64,7 @@ sources = \ StructField.cs \ StructGen.cs \ SymbolTable.cs \ + UnionGen.cs \ VirtualMethod.cs \ VMSignature.cs \ XmlElementExtensions.cs diff --git a/generator/Parameters.cs b/generator/Parameters.cs index 2ea48d260..ae953ab7e 100644 --- a/generator/Parameters.cs +++ b/generator/Parameters.cs @@ -93,23 +93,23 @@ namespace GtkSharp.Generation { if (HasCB || HideData) { - foreach (Parameter param in param_list) { - if (param.Closure == idx) + if (Parser.GetVersion (elem.OwnerDocument.DocumentElement) >= 3) { + foreach (Parameter param in param_list) { + if (param.Closure == idx) + return true; + if (param.DestroyNotify == idx) + return true; + } + } else { + if (p.IsUserData && (idx == Count - 1)) return true; - else if (param.DestroyNotify == idx) + if (p.IsUserData && (idx == Count - 2) && this [Count - 1] is ErrorParameter) + return true; + if (p.IsUserData && idx > 0 && this [idx - 1].Generatable is CallbackGen) + return true; + if (p.IsDestroyNotify && (idx == Count - 1) && this [idx - 1].IsUserData) return true; } - - if (p.IsUserData && (idx == Count - 1)) - return true; - if (p.IsUserData && (idx == Count - 2) && this [Count - 1] is ErrorParameter) - return true; - if (p.IsUserData && idx > 0 && - this [idx - 1].Generatable is CallbackGen) - return true; - if (p.IsDestroyNotify && (idx == Count - 1) && - this [idx - 1].IsUserData) - return true; } return false; @@ -234,7 +234,8 @@ namespace GtkSharp.Generation { param_list.Add (p); } - if (has_cb && Count > 2 && this [Count - 3].Generatable is CallbackGen && this [Count - 2].IsUserData && this [Count - 1].IsDestroyNotify) + if (Parser.GetVersion (elem.OwnerDocument.DocumentElement) < 3 && + has_cb && Count > 2 && this [Count - 3].Generatable is CallbackGen && this [Count - 2].IsUserData && this [Count - 1].IsDestroyNotify) this [Count - 3].Scope = "notified"; valid = true; diff --git a/generator/Parser.cs b/generator/Parser.cs index b7bfa5f98..0974d5908 100644 --- a/generator/Parser.cs +++ b/generator/Parser.cs @@ -171,6 +171,9 @@ namespace GtkSharp.Generation { case "class": result.Add (new ClassGen (ns, elem)); break; + case "union": + result.Add (new UnionGen (ns, elem)); + break; case "struct": if (is_opaque) { result.Add (new OpaqueGen (ns, elem)); diff --git a/generator/StructBase.cs b/generator/StructBase.cs index 6fc7bcde5..9288fc3a4 100644 --- a/generator/StructBase.cs +++ b/generator/StructBase.cs @@ -110,6 +110,12 @@ namespace GtkSharp.Generation { } } + public virtual bool Union { + get { + return false; + } + } + protected void GenEqualsAndHash (StreamWriter sw) { int bitfields = 0; @@ -172,12 +178,13 @@ namespace GtkSharp.Generation { { int bitfields = 0; bool need_field = true; + StreamWriter sw = gen_info.Writer; foreach (StructField field in fields) { + if (Union) + sw.WriteLine ("\t\t[FieldOffset(0)]"); if (field.IsBitfield) { if (need_field) { - StreamWriter sw = gen_info.Writer; - sw.WriteLine ("\t\tprivate uint _bitfield{0};\n", bitfields++); need_field = false; } @@ -221,7 +228,10 @@ namespace GtkSharp.Generation { sw.WriteLine ("#region Autogenerated code"); if (IsDeprecated) sw.WriteLine ("\t[Obsolete]"); - sw.WriteLine ("\t[StructLayout(LayoutKind.Sequential)]"); + if (Union) + sw.WriteLine ("\t[StructLayout(LayoutKind.Explicit)]"); + else + sw.WriteLine ("\t[StructLayout(LayoutKind.Sequential)]"); string access = IsInternal ? "internal" : "public"; sw.WriteLine ("\t" + access + " partial struct {0} : IEquatable<{0}> {{", Name); sw.WriteLine (); diff --git a/generator/StructField.cs b/generator/StructField.cs index ac885038e..e0ba545d4 100644 --- a/generator/StructField.cs +++ b/generator/StructField.cs @@ -80,7 +80,7 @@ namespace GtkSharp.Generation { return StudlyName; else if (IsBitfield) return Name; - else if (IsPointer && (gen is StructGen || gen is BoxedGen)) + else if (IsPointer && (gen is StructGen || gen is BoxedGen || gen is UnionGen)) return Access != "private" ? wrapped_name : Name; else if (IsPointer && CSType != "string") return Name; @@ -148,7 +148,7 @@ namespace GtkSharp.Generation { acc.WriteAccessors (sw, indent + "\t", Name); sw.WriteLine (indent + "}"); } - } else if (IsPointer && (gen is StructGen || gen is BoxedGen)) { + } else if (IsPointer && (gen is StructGen || gen is BoxedGen || gen is UnionGen)) { sw.WriteLine (indent + "private {0} {1};", CSType, Name); sw.WriteLine (); if (Access != "private") { diff --git a/generator/SymbolTable.cs b/generator/SymbolTable.cs index e4cca25d7..823494a97 100644 --- a/generator/SymbolTable.cs +++ b/generator/SymbolTable.cs @@ -292,6 +292,13 @@ namespace GtkSharp.Generation { return false; } + + public bool IsUnion (string c_type) + { + if (this[c_type] is UnionGen) + return true; + return false; + } public bool IsEnum(string c_type) { diff --git a/generator/UnionGen.cs b/generator/UnionGen.cs new file mode 100644 index 000000000..15589b262 --- /dev/null +++ b/generator/UnionGen.cs @@ -0,0 +1,18 @@ + +using System.Xml; + +namespace GtkSharp.Generation +{ + public class UnionGen : StructBase { + + public UnionGen (XmlElement ns, XmlElement elem) : base (ns, elem) + { + } + + public override bool Union { + get { + return true; + } + } + } +} diff --git a/generator/generator.csproj b/generator/generator.csproj index 41ccce2e6..1d19e62ae 100644 --- a/generator/generator.csproj +++ b/generator/generator.csproj @@ -92,6 +92,7 @@ +