generator: Use a new AbiStruct object to handle wrapped type ABI

This allows us to totally get rid of the glue as this new class
handles bitfields and union properly.
This commit is contained in:
Thibault Saunier 2017-10-03 10:18:08 -03:00
parent 7d902ef7e4
commit 248278d267
28 changed files with 1011 additions and 115 deletions

View file

@ -147,7 +147,7 @@ namespace GtkSharp.Generation {
} }
} }
protected virtual bool CanGenerateABIStruct(LogWriter log) { public virtual bool CanGenerateABIStruct(LogWriter log) {
return (abi_fields_valid); return (abi_fields_valid);
} }
@ -165,7 +165,7 @@ namespace GtkSharp.Generation {
if (parent != null) { if (parent != null) {
// FIXME Add that information to ManualGen and use it. // FIXME Add that information to ManualGen and use it.
if (parent.CName == "GInitiallyUnowned" || parent.CName == "GObject") { if (parent.CName == "GInitiallyUnowned" || parent.CName == "GObject") {
cs_parent_struct = "GLib.Object.GObject"; cs_parent_struct = "GLib.Object";
} else { } else {
parent_can_generate = false; parent_can_generate = false;
var _parent = parent as ClassBase; var _parent = parent as ClassBase;
@ -175,9 +175,8 @@ namespace GtkSharp.Generation {
parent_can_generate = _parent.CheckABIStructParent(log, out tmp); parent_can_generate = _parent.CheckABIStructParent(log, out tmp);
} }
if (parent_can_generate) { if (parent_can_generate)
cs_parent_struct = cs_parent + "._" + parent.CName + "ABI"; cs_parent_struct = cs_parent;
}
} }
if (!parent_can_generate) { if (!parent_can_generate) {
@ -191,16 +190,6 @@ namespace GtkSharp.Generation {
return parent_can_generate; return parent_can_generate;
} }
protected virtual void WriteInstanceOffsetMethod(StreamWriter sw,
string cs_parent_struct) {
string cs_parent = SymbolTable.Table.GetCSType(Elem.GetAttribute("parent"));
if (cs_parent_struct == "")
sw.WriteLine ("\t\tpublic static uint instance_offset { get { return 0; }}");
else
sw.WriteLine ("\t\tpublic static new uint instance_offset {{ get {{ return ((uint) Marshal.SizeOf(typeof ({0})) + {1}.instance_offset); }} }}", cs_parent_struct, cs_parent);
}
protected void GenerateStructureABI (GenerationInfo gen_info) protected void GenerateStructureABI (GenerationInfo gen_info)
{ {
string cs_parent_struct = null; string cs_parent_struct = null;
@ -215,19 +204,52 @@ namespace GtkSharp.Generation {
if (cs_parent_struct != "") if (cs_parent_struct != "")
_new = "new "; _new = "new ";
WriteInstanceOffsetMethod(sw, cs_parent_struct);
sw.WriteLine (); sw.WriteLine ();
sw.WriteLine ("\t\tpublic " + _new + " unsafe uint GetFieldOffset(string field) {"); sw.WriteLine ("\t\t// Internal representation of the wrapped structure ABI.");
sw.WriteLine ("\t\t\treturn (uint) (instance_offset + (uint) Marshal.OffsetOf(typeof({0}), field));", sw.WriteLine ("\t\tstatic GLib.AbiStruct _abi_info = null;");
(QualifiedName + "._" + CName + "ABI")); sw.WriteLine ("\t\tstatic public " + _new + "GLib.AbiStruct abi_info {");
sw.WriteLine ("\t\t\tget {");
sw.WriteLine ("\t\t\t\tif (_abi_info == null)");
sw.WriteLine ("\t\t\t\t\t_abi_info = new GLib.AbiStruct (new List<GLib.AbiField>{ ");
// Generate Tests
if (abi_fields.Count > 0 && gen_info.CAbiWriter != null) {
gen_info.CAbiWriter.WriteLine("\tg_print(\"\\\"sizeof({0}.{1})\\\": \\\"%\" G_GOFFSET_FORMAT \"\\\"\\n\", sizeof({2}));", NS, Name, CName);
gen_info.AbiWriter.WriteLine("\t\t\tConsole.WriteLine(\"\\\"sizeof({0}.{1})\\\": \\\"\" + {0}.{1}.abi_info.Size + \"\\\"\");", NS, Name);
}
StructABIField prev = null;
StructABIField next = null;
StringWriter field_alignment_structures_writer = new StringWriter();
for(int i=0; i < abi_fields.Count; i++) {
var field = abi_fields[i];
next = abi_fields.Count > i +1 ? abi_fields[i + 1] : null;
prev = field.Generate(gen_info, "\t\t\t\t\t", prev, next, cs_parent_struct,
field_alignment_structures_writer);
var union = field as UnionABIField;
if (union == null && gen_info.CAbiWriter != null) {
gen_info.AbiWriter.WriteLine("\t\t\tConsole.WriteLine(\"\\\"{0}.{1}.{2}\\\": \\\"\" + {0}.{1}.abi_info.GetFieldOffset(\"{2}\") + \"\\\"\");", NS, Name, field.CName);
gen_info.CAbiWriter.WriteLine("\tg_print(\"\\\"{0}.{1}.{2}\\\": \\\"%\" G_GOFFSET_FORMAT \"\\\"\\n\", G_STRUCT_OFFSET({3}, {2}));", NS, Name, field.CName, CName);
}
}
if (abi_fields.Count > 0 && gen_info.CAbiWriter != null) {
gen_info.AbiWriter.Flush();
gen_info.CAbiWriter.Flush();
}
sw.WriteLine ("\t\t\t\t\t});");
sw.WriteLine ();
sw.WriteLine ("\t\t\t\treturn _abi_info;");
sw.WriteLine ("\t\t\t}");
sw.WriteLine ("\t\t}"); sw.WriteLine ("\t\t}");
sw.WriteLine (); sw.WriteLine ();
sw.WriteLine ("\t\t[StructLayout (LayoutKind.Sequential)]"); sw.WriteLine (field_alignment_structures_writer.ToString());
sw.WriteLine ("\t\tpublic struct _" + CName + "ABI" + " {"); sw.WriteLine ("\t\t// End of the ABI representation.");
foreach (StructABIField field in abi_fields)
field.Generate (gen_info, "\t\t\t");
sw.WriteLine ("\t\t}");
sw.WriteLine (); sw.WriteLine ();
} }
@ -251,6 +273,10 @@ namespace GtkSharp.Generation {
if (!abi_field.Validate(log)) if (!abi_field.Validate(log))
abi_fields_valid = false; abi_fields_valid = false;
} }
if (abi_fields_valid)
foreach (StructABIField abi_field in abi_fields) {
abi_field.SetGetOffseName();
}
ArrayList invalids = new ArrayList (); ArrayList invalids = new ArrayList ();
@ -348,9 +374,10 @@ namespace GtkSharp.Generation {
protected void GenFields (GenerationInfo gen_info) protected void GenFields (GenerationInfo gen_info)
{ {
foreach (ObjectField field in fields.Values) foreach (ObjectField field in fields.Values) {
field.Generate (gen_info, "\t\t"); field.Generate (gen_info, "\t\t");
} }
}
protected void GenConstants (GenerationInfo gen_info) protected void GenConstants (GenerationInfo gen_info)
{ {

View file

@ -34,9 +34,13 @@ namespace GtkSharp.Generation {
public static int Main (string[] args) public static int Main (string[] args)
{ {
bool show_help = false; bool show_help = false;
bool all_opaque = true;
string dir = ""; string dir = "";
string assembly_name = ""; string assembly_name = "";
string gapidir = ""; string gapidir = "";
string abi_cs_usings = "";
string abi_cs_file = "";
string abi_c_file = "";
string glue_filename = ""; string glue_filename = "";
string glue_includes = ""; string glue_includes = "";
string gluelib_name = ""; string gluelib_name = "";
@ -59,6 +63,12 @@ namespace GtkSharp.Generation {
(string v) => { assembly_name = v; } }, (string v) => { assembly_name = v; } },
{ "gapidir=", "GAPI xml data folder.", { "gapidir=", "GAPI xml data folder.",
(string v) => { gapidir = v; } }, (string v) => { gapidir = v; } },
{ "abi-cs-filename=", "Filename for the generated CSharp ABI checker.",
(string v) => { abi_cs_file = v; } },
{ "abi-cs-usings=", "Namespaces to use in the CS ABI checker.",
(string v) => { abi_cs_usings = v; } },
{ "abi-c-filename=", "Filename for the generated C ABI checker.",
(string v) => { abi_c_file = v; } },
{ "glue-filename=", "Filename for the generated C glue code.", { "glue-filename=", "Filename for the generated C glue code.",
(string v) => { glue_filename = v; } }, (string v) => { glue_filename = v; } },
{ "glue-includes=", "Content of #include directive to add in the generated C glue code.", { "glue-includes=", "Content of #include directive to add in the generated C glue code.",
@ -130,7 +140,8 @@ namespace GtkSharp.Generation {
GenerationInfo gen_info = null; GenerationInfo gen_info = null;
if (dir != "" || assembly_name != "" || glue_filename != "" || glue_includes != "" || gluelib_name != "") if (dir != "" || assembly_name != "" || glue_filename != "" || glue_includes != "" || gluelib_name != "")
gen_info = new GenerationInfo (dir, assembly_name, glue_filename, glue_includes, gluelib_name); gen_info = new GenerationInfo (dir, assembly_name, glue_filename, glue_includes, gluelib_name,
abi_c_file, abi_cs_file, abi_cs_usings);
foreach (IGeneratable gen in gens) { foreach (IGeneratable gen in gens) {
if (gen_info == null) if (gen_info == null)
@ -142,7 +153,7 @@ namespace GtkSharp.Generation {
ObjectGen.GenerateMappers (); ObjectGen.GenerateMappers ();
if (gen_info != null) if (gen_info != null)
gen_info.CloseGlueWriter (); gen_info.CloseWriters ();
Statistics.Report(); Statistics.Report();
return 0; return 0;

View file

@ -83,6 +83,11 @@ namespace GtkSharp.Generation {
return "(" + QualifiedName + ") " + var; return "(" + QualifiedName + ") " + var;
} }
public override string GenerateAlign () {
return null;
}
public override void Generate (GenerationInfo gen_info) public override void Generate (GenerationInfo gen_info)
{ {
StreamWriter sw = gen_info.OpenStream (Name, NS); StreamWriter sw = gen_info.OpenStream (Name, NS);

View file

@ -27,6 +27,8 @@ namespace GtkSharp.Generation {
public abstract class FieldBase : PropertyBase { public abstract class FieldBase : PropertyBase {
public FieldBase abi_field = null; public FieldBase abi_field = null;
string getterName, setterName;
protected string getOffsetName, offsetName;
public FieldBase (XmlElement elem, ClassBase container_type) : base (elem, container_type) {} public FieldBase (XmlElement elem, ClassBase container_type) : base (elem, container_type) {}
public FieldBase (XmlElement elem, ClassBase container_type, FieldBase abi_field) : base (elem, container_type) { public FieldBase (XmlElement elem, ClassBase container_type, FieldBase abi_field) : base (elem, container_type) {
@ -97,13 +99,13 @@ namespace GtkSharp.Generation {
} }
private bool UseABIStruct(GenerationInfo gen_info) { private bool UseABIStruct(GenerationInfo gen_info) {
if (!container_type.CanGenerateABIStruct(new LogWriter(container_type.CName)))
return false;
return (abi_field != null && abi_field.getOffsetName != null && return (abi_field != null && abi_field.getOffsetName != null &&
gen_info.GlueWriter == null); gen_info.GlueWriter == null);
} }
string getterName, setterName;
protected string getOffsetName, offsetName;
void CheckGlue (GenerationInfo gen_info) void CheckGlue (GenerationInfo gen_info)
{ {
getterName = setterName = getOffsetName = null; getterName = setterName = getOffsetName = null;
@ -112,7 +114,7 @@ namespace GtkSharp.Generation {
if (UseABIStruct(gen_info)) { if (UseABIStruct(gen_info)) {
getOffsetName = abi_field.getOffsetName; getOffsetName = abi_field.getOffsetName;
offsetName = "GetFieldOffset(\"" + ((StructField)abi_field).EqualityName + "\")"; offsetName = "abi_info.GetFieldOffset(\"" + ((StructField)abi_field).CName + "\")";
return; return;
} }

View file

@ -96,6 +96,14 @@ namespace GtkSharp.Generation {
public abstract bool Validate (); public abstract bool Validate ();
public virtual string GenerateGetSizeOf () {
return null;
}
public virtual string GenerateAlign () {
return null;
}
public void Generate () public void Generate ()
{ {
GenerationInfo geninfo = new GenerationInfo (ns); GenerationInfo geninfo = new GenerationInfo (ns);

View file

@ -33,7 +33,11 @@ namespace GtkSharp.Generation {
string gluelib_name; string gluelib_name;
bool glue_enabled; bool glue_enabled;
StreamWriter sw; StreamWriter sw;
StreamWriter abiwriter = null;
StreamWriter cabiwriter = null;
StreamWriter glue_sw; StreamWriter glue_sw;
string abicfile = null;
string abicsfile = null;
public GenerationInfo (XmlElement ns) public GenerationInfo (XmlElement ns)
{ {
@ -43,17 +47,23 @@ namespace GtkSharp.Generation {
assembly_name = ns_name.ToLower () + "-sharp"; assembly_name = ns_name.ToLower () + "-sharp";
} }
public GenerationInfo (string dir, string assembly_name) : this (dir, assembly_name, "", "", "") {} public GenerationInfo (string dir, string assembly_name) :
this (dir, assembly_name, "", "", "", "", "", "") {}
public GenerationInfo (string dir, string assembly_name, string glue_filename, string glue_includes, string gluelib_name) public GenerationInfo (string dir, string assembly_name, string glue_filename,
string glue_includes, string gluelib_name, string abi_c_file,
string abi_cs_file, string abi_cs_usings)
{ {
this.dir = dir; this.dir = dir;
this.assembly_name = assembly_name; this.assembly_name = assembly_name;
this.gluelib_name = gluelib_name; this.gluelib_name = gluelib_name;
InitializeGlue (glue_filename, glue_includes, gluelib_name); abicfile = abi_c_file;
abicsfile = abi_cs_file;
InitializeWriters (glue_filename, glue_includes, gluelib_name, abi_cs_usings);
} }
void InitializeGlue (string glue_filename, string glue_includes, string gluelib_name) void InitializeWriters (string glue_filename, string glue_includes, string gluelib_name,
string abi_cs_usings)
{ {
if (gluelib_name != String.Empty && glue_filename != String.Empty) { if (gluelib_name != String.Empty && glue_filename != String.Empty) {
FileStream stream; FileStream stream;
@ -79,6 +89,44 @@ namespace GtkSharp.Generation {
} }
glue_enabled = true; glue_enabled = true;
} }
if (cabiwriter == null && abicfile != "" && abicsfile != "" && abi_cs_usings != "") {
var stream = new FileStream (abicfile, FileMode.Create, FileAccess.Write);
cabiwriter = new StreamWriter (stream);
cabiwriter.WriteLine ("// This file was generated by the Gtk# code generator.");
cabiwriter.WriteLine ("// Any changes made will be lost if regenerated.");
cabiwriter.WriteLine ();
if (glue_includes != "") {
foreach (string header in glue_includes.Split (new char[] {',', ' '})) {
if (header != "")
cabiwriter.WriteLine ("#include <{0}>", header);
}
cabiwriter.WriteLine ("");
}
cabiwriter.WriteLine ("int main (int argc, char *argv[]) {");
stream = new FileStream (abicsfile, FileMode.Create, FileAccess.Write);
abiwriter = new StreamWriter (stream);
abiwriter.WriteLine ("// This file was generated by the Gtk# code generator.");
abiwriter.WriteLine ("// Any changes made will be lost if regenerated.");
abiwriter.WriteLine ();
var name = "";
foreach (string _using in abi_cs_usings.Split (new char[] {',', ' '})) {
if (_using != "") {
abiwriter.WriteLine ("using {0};", _using);
if (name == "")
name = _using;
}
}
abiwriter.WriteLine ("using System;");
abiwriter.WriteLine ();
abiwriter.WriteLine ("namespace AbiTester {");
abiwriter.WriteLine ("\tclass ___" + name + " {");
abiwriter.WriteLine ("\t\tpublic static void Main (string[] args) {");
}
} }
public string AssemblyName { public string AssemblyName {
@ -87,6 +135,18 @@ namespace GtkSharp.Generation {
} }
} }
public StreamWriter AbiWriter {
get {
return abiwriter;
}
}
public StreamWriter CAbiWriter {
get {
return cabiwriter;
}
}
public string Dir { public string Dir {
get { get {
return dir; return dir;
@ -120,10 +180,22 @@ namespace GtkSharp.Generation {
} }
} }
public void CloseGlueWriter () public void CloseWriters ()
{ {
if (glue_sw != null) if (glue_sw != null)
glue_sw.Close (); glue_sw.Close ();
if (cabiwriter != null) {
cabiwriter.WriteLine ("\treturn 0;");
cabiwriter.WriteLine ("}");
cabiwriter.Close();
abiwriter.WriteLine ("\t\t}");
abiwriter.WriteLine ("\t}");
abiwriter.WriteLine ("}");
abiwriter.Close();
}
} }
string member; string member;

View file

@ -48,6 +48,12 @@ namespace GtkSharp.Generation {
// Generates an expression to convert var from MarshalType // Generates an expression to convert var from MarshalType
string FromNative (string var); string FromNative (string var);
// Generates code to get size of the type
string GenerateGetSizeOf ();
// Generates code to get size of the type
string GenerateAlign ();
bool Validate (); bool Validate ();
void Generate (); void Generate ();

View file

@ -27,6 +27,7 @@ namespace GtkSharp.Generation {
public class ManualGen : SimpleBase { public class ManualGen : SimpleBase {
string from_fmt; string from_fmt;
string abi_type;
public ManualGen (string ctype, string type) : base (ctype, type, "null") public ManualGen (string ctype, string type) : base (ctype, type, "null")
{ {
@ -38,12 +39,24 @@ namespace GtkSharp.Generation {
this.from_fmt = from_fmt; this.from_fmt = from_fmt;
} }
public ManualGen (string ctype, string type, string from_fmt, string abi_type) : base (ctype, type, "null")
{
this.from_fmt = from_fmt;
this.abi_type = abi_type;
}
public override string MarshalType { public override string MarshalType {
get { get {
return "IntPtr"; return "IntPtr";
} }
} }
public string AbiType {
get {
return abi_type;
}
}
public override string CallByName (string var_name) public override string CallByName (string var_name)
{ {
return var_name + " == null ? IntPtr.Zero : " + var_name + ".Handle"; return var_name + " == null ? IntPtr.Zero : " + var_name + ".Handle";
@ -53,6 +66,10 @@ namespace GtkSharp.Generation {
{ {
return String.Format (from_fmt, var); return String.Format (from_fmt, var);
} }
public override string GenerateGetSizeOf () {
return "(uint) Marshal.SizeOf(typeof(" + abi_type + "))";
}
} }
} }

View file

@ -187,7 +187,7 @@ namespace GtkSharp.Generation {
} }
} }
protected override bool CanGenerateABIStruct(LogWriter log) { public override bool CanGenerateABIStruct(LogWriter log) {
if (!abi_fields_valid) { if (!abi_fields_valid) {
log.Info(CName + " has invalid fields"); log.Info(CName + " has invalid fields");
@ -338,5 +338,8 @@ namespace GtkSharp.Generation {
return true; return true;
} }
public override string GenerateGetSizeOf () {
return NS + "." + Name + ".abi_info.GetABISize()";
}
} }
} }

View file

@ -175,7 +175,6 @@ namespace GtkSharp.Generation {
sw.WriteLine (" {"); sw.WriteLine (" {");
sw.WriteLine (); sw.WriteLine ();
GenerateStructureABI (gen_info);
GenCtors (gen_info); GenCtors (gen_info);
GenProperties (gen_info, null); GenProperties (gen_info, null);
GenFields (gen_info); GenFields (gen_info);
@ -248,6 +247,7 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\t\t}"); sw.WriteLine ("\t\t}");
} }
GenerateStructureABI (gen_info);
sw.WriteLine ("#endregion"); sw.WriteLine ("#endregion");
sw.WriteLine ("\t}"); sw.WriteLine ("\t}");
@ -426,5 +426,6 @@ namespace GtkSharp.Generation {
sw.Close (); sw.Close ();
} }
} }
} }

View file

@ -80,7 +80,6 @@ namespace GtkSharp.Generation {
sw.WriteLine (" {"); sw.WriteLine (" {");
sw.WriteLine (); sw.WriteLine ();
GenerateStructureABI(gen_info);
GenConstants (gen_info); GenConstants (gen_info);
GenFields (gen_info); GenFields (gen_info);
GenMethods (gen_info, null, null); GenMethods (gen_info, null, null);
@ -196,6 +195,7 @@ namespace GtkSharp.Generation {
sw.WriteLine (); sw.WriteLine ();
} }
GenerateStructureABI(gen_info);
sw.WriteLine ("#endregion"); sw.WriteLine ("#endregion");
sw.WriteLine ("\t}"); sw.WriteLine ("\t}");

View file

@ -26,7 +26,7 @@ namespace GtkSharp.Generation {
public abstract class PropertyBase { public abstract class PropertyBase {
protected XmlElement elem; protected XmlElement elem;
protected ClassBase container_type; public ClassBase container_type;
public PropertyBase (XmlElement elem, ClassBase container_type) public PropertyBase (XmlElement elem, ClassBase container_type)
{ {
@ -40,7 +40,7 @@ namespace GtkSharp.Generation {
} }
} }
public string CName { public virtual string CName {
get { get {
return elem.GetAttribute ("cname"); return elem.GetAttribute ("cname");
} }

View file

@ -94,6 +94,14 @@ namespace GtkSharp.Generation {
public void Generate (GenerationInfo gen_info) public void Generate (GenerationInfo gen_info)
{ {
} }
public virtual string GenerateGetSizeOf () {
return null;
}
public virtual string GenerateAlign () {
return null;
}
} }
} }

View file

@ -24,8 +24,16 @@ namespace GtkSharp.Generation {
using System; using System;
public class SimpleGen : SimpleBase { public class SimpleGen : SimpleBase {
string size_of;
public SimpleGen (string ctype, string type, string default_value) : base (ctype, type, default_value) {} public SimpleGen (string ctype, string type, string default_value) : base (ctype, type, default_value) {}
public SimpleGen (string ctype, string type, string default_value, string size_of) : base (ctype, type, default_value) {
this.size_of = size_of;
}
public override string GenerateGetSizeOf () {
return size_of;
}
} }
} }

View file

@ -7,14 +7,23 @@ namespace GtkSharp.Generation {
public class StructABIField : StructField { public class StructABIField : StructField {
protected new ClassBase container_type; protected new ClassBase container_type;
public string parent_structure_name;
public StructABIField (XmlElement elem, ClassBase container_type) : base (elem, container_type) { public StructABIField (XmlElement elem, ClassBase container_type) : base (elem, container_type) {
this.container_type = container_type; this.container_type = container_type;
this.getOffsetName = null; this.getOffsetName = null;
} }
public override string CName {
get {
if (parent_structure_name != null)
return parent_structure_name + '.' + elem.GetAttribute ("cname");
return elem.GetAttribute ("cname");
}
}
public override void Generate (GenerationInfo gen_info, string indent) { public override void Generate (GenerationInfo gen_info, string indent) {
this.getOffsetName = "Get" + CName + "Offset";
base.Generate(gen_info, indent); base.Generate(gen_info, indent);
} }
@ -41,20 +50,89 @@ namespace GtkSharp.Generation {
if (cstype == null || cstype == "") { if (cstype == null || cstype == "") {
log.Warn (" field \"" + CName + "\" has no cstype, can't generate ABI field."); log.Warn (" field \"" + CName + "\" has no cstype, can't generate ABI field.");
return false; return false;
} }
if (!base.Validate (log)) if (!base.Validate (log))
return false; return false;
if (IsBitfield) {
log.Warn ("bitfields are not supported");
return false;
}
return true; return true;
} }
public void SetGetOffseName() {
this.getOffsetName = "Get" + CName + "Offset";
}
public override string GenerateGetSizeOf(string indent) {
return base.GenerateGetSizeOf(indent) + " // " + CName;
}
public virtual StructABIField Generate (GenerationInfo gen_info, string indent,
StructABIField prev_field, StructABIField next_field, string parent_name,
TextWriter structw) {
StreamWriter sw = gen_info.Writer;
IGeneratable gen = SymbolTable.Table[CType];
sw.WriteLine("{0}\tnew GLib.AbiField(\"{1}\"", indent, CName);
indent = indent + "\t\t";
if (prev_field != null) {
sw.WriteLine(indent + ", -1");
} else {
if (parent_name != "")
sw.WriteLine(indent + ", " + parent_name + ".abi_info.Fields");
else
sw.WriteLine(indent + ", 0");
}
sw.WriteLine(indent + ", " + GenerateGetSizeOf(""));
var prev_field_name = prev_field != null ? "\"" + prev_field.CName + "\"" : "null";
sw.WriteLine(indent + ", " + prev_field_name);
var container_name = container_type.CName.Replace(".", "_");
var sanitized_name = CName.Replace(".", "_");
var alig_struct_name = container_name + "_" + sanitized_name + "Align";
var next_field_name = next_field != null ? "\"" + next_field.CName + "\"" : "null";
sw.WriteLine(indent + ", " + next_field_name);
if (structw != null) {
string min_align = gen != null ? gen.GenerateAlign() : null;
// Do not generate structs if the type is a simple pointer.
if (IsCPointer())
min_align = "(uint) Marshal.SizeOf(typeof(IntPtr))";
if (min_align == null) {
var tmpindent = "\t\t";
structw.WriteLine(tmpindent + "[StructLayout(LayoutKind.Sequential)]");
structw.WriteLine(tmpindent + "public struct " + alig_struct_name);
structw.WriteLine(tmpindent + "{");
structw.WriteLine(tmpindent + "\tsbyte f1;");
base.Generate(gen_info, tmpindent + "\t", true, structw);
structw.WriteLine(tmpindent + "}");
structw.WriteLine();
var fieldname = SymbolTable.Table.MangleName (CName).Replace(".", "_");
if (IsArray && IsNullTermArray)
fieldname += "Ptr";
sw.WriteLine(indent + ", (long) Marshal.OffsetOf(typeof(" + alig_struct_name + "), \"" + fieldname + "\")");
} else {
sw.WriteLine(indent + ", " + min_align);
} }
} }
gen_info.Writer = sw;
uint bits = 0;
var bitsstr = elem.GetAttribute("bits");
if (bitsstr != null && bitsstr != "")
bits = (uint) Int32.Parse(bitsstr);
sw.WriteLine(indent + ", " + bits);
sw.WriteLine(indent + "),");
return this;
}
}
}

View file

@ -60,13 +60,6 @@ namespace GtkSharp.Generation {
} }
} }
protected override void WriteInstanceOffsetMethod(StreamWriter sw, string cs_parent_struct) {
if (cs_parent_struct == "")
sw.WriteLine ("\t\tpublic uint instance_offset { get { return 0; }}");
else
sw.WriteLine ("\t\tpublic new uint instance_offset {{ get {{ return ((uint) Marshal.SizeOf(typeof ({0})) + base.instance_offset); }} }}", cs_parent_struct);
}
public override string DefaultValue { public override string DefaultValue {
get { get {
return QualifiedName + ".Zero"; return QualifiedName + ".Zero";
@ -134,7 +127,7 @@ namespace GtkSharp.Generation {
equals.Append ("true"); equals.Append ("true");
foreach (StructField field in fields) { foreach (StructField field in fields) {
if (field.IsPadding) if (field.IsPadding || field.Hidden)
continue; continue;
if (field.IsBitfield) { if (field.IsBitfield) {
if (need_field) { if (need_field) {
@ -217,9 +210,16 @@ namespace GtkSharp.Generation {
return base.Validate (); return base.Validate ();
} }
public override bool CanGenerateABIStruct(LogWriter log) {
log.Info("Not generating any ABI structs for managed structures");
return false;
}
public override void Generate (GenerationInfo gen_info) public override void Generate (GenerationInfo gen_info)
{ {
bool need_close = false; bool need_close = false;
if (gen_info.Writer == null) { if (gen_info.Writer == null) {
gen_info.Writer = gen_info.OpenStream (Name, NS); gen_info.Writer = gen_info.OpenStream (Name, NS);
need_close = true; need_close = true;

View file

@ -41,7 +41,7 @@ namespace GtkSharp.Generation {
} }
} }
int ArrayLength { public int ArrayLength {
get { get {
if (!IsArray) if (!IsArray)
return 0; return 0;
@ -60,7 +60,7 @@ namespace GtkSharp.Generation {
} }
} }
bool IsNullTermArray { public bool IsNullTermArray {
get { return elem.GetAttributeAsBoolean ("null_term_array"); } get { return elem.GetAttributeAsBoolean ("null_term_array"); }
} }
@ -102,6 +102,54 @@ namespace GtkSharp.Generation {
} }
} }
bool IsFixedSizeArray() {
return IsArray && !IsNullTermArray && ArrayLength != 0;
}
public bool IsCPointer() {
IGeneratable gen = SymbolTable.Table[CType];
return (CType.EndsWith("*") ||
CType.EndsWith ("pointer") ||
gen is CallbackGen ||
cstype == "string" ||
(CType == "guint8" && (IsArray && IsNullTermArray)) ||
elem.GetAttributeAsBoolean("is_callback"));
}
public virtual string GenerateGetSizeOf(string indent) {
string cstype = SymbolTable.Table.GetCSType(CType, true);
string res = "";
IGeneratable gen = SymbolTable.Table[CType];
var is_pointer = false;
if (IsCPointer()) {
is_pointer = true;
cstype = "IntPtr";
} else if (gen != null) {
res = gen.GenerateGetSizeOf();
}
if (res != null && res != "") {
if (IsFixedSizeArray())
res += " * " + ArrayLength;
return indent + res;
}
var _enum = gen as EnumGen;
if (_enum != null && !is_pointer)
res = "(uint) Marshal.SizeOf(System.Enum.GetUnderlyingType(typeof(" + cstype + ")))";
else
res = "(uint) Marshal.SizeOf(typeof(" + cstype + "))";
if (IsFixedSizeArray())
res += " * " + ArrayLength;
return res;
}
public bool IsPadding { public bool IsPadding {
get { get {
if (elem.GetAttributeAsBoolean ("is-padding")) if (elem.GetAttributeAsBoolean ("is-padding"))
@ -114,7 +162,7 @@ namespace GtkSharp.Generation {
public bool IsPointer { public bool IsPointer {
get { get {
return (CType.EndsWith ("*") || CType.EndsWith ("pointer")); return IsCPointer();
} }
} }
@ -141,60 +189,85 @@ namespace GtkSharp.Generation {
public override void Generate (GenerationInfo gen_info, string indent) public override void Generate (GenerationInfo gen_info, string indent)
{ {
if (Hidden) Generate(gen_info, indent, false, gen_info.Writer);
}
public void Generate (GenerationInfo gen_info, string indent, bool use_cnames,
TextWriter sw)
{
if (Hidden && !use_cnames)
return; return;
visible = Access != "private"; visible = Access != "private";
StreamWriter sw = gen_info.Writer;
SymbolTable table = SymbolTable.Table; SymbolTable table = SymbolTable.Table;
string wrapped = table.GetCSType (CType); string wrapped = table.GetCSType (CType);
string wrapped_name = SymbolTable.Table.MangleName (CName); string wrapped_name = SymbolTable.Table.MangleName (CName);
string name = Name;
string studly_name = StudlyName;
string cstype = CSType;
IGeneratable gen = table [CType]; IGeneratable gen = table [CType];
if (use_cnames) {
name = studly_name = wrapped_name = SymbolTable.Table.MangleName (CName).Replace(".", "_");
var mangen = gen as ManualGen;
if (mangen != null) {
if (mangen.AbiType != null)
cstype = mangen.AbiType;
}
if (IsCPointer())
cstype = "IntPtr";
}
if (IsArray && !IsNullTermArray) { if (IsArray && !IsNullTermArray) {
sw.WriteLine (indent + "[MarshalAs (UnmanagedType.ByValArray, SizeConst=" + ArrayLength + ")]"); sw.WriteLine (indent + "[MarshalAs (UnmanagedType.ByValArray, SizeConst=" + ArrayLength + ")]");
sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, StudlyName); sw.WriteLine (indent + "{0} {1} {2};", Access, cstype, studly_name);
} else if (IsArray && IsNullTermArray) { } else if (IsArray && IsNullTermArray) {
sw.WriteLine (indent + "private {0} {1};", "IntPtr", StudlyName+ "Ptr"); sw.WriteLine (indent + "private {0} {1};", "IntPtr", studly_name+ "Ptr");
if ((Readable || Writable) && Access == "public") { if ((Readable || Writable) && Access == "public") {
sw.WriteLine (indent + "public {0} {1} {{", CSType, StudlyName); sw.WriteLine (indent + "public {0} {1} {{", cstype, studly_name);
if (Readable) if (Readable)
sw.WriteLine (indent + "\tget {{ return GLib.Marshaller.StructArrayFromNullTerminatedIntPtr<{0}> ({1}); }}", sw.WriteLine (indent + "\tget {{ return GLib.Marshaller.StructArrayFromNullTerminatedIntPtr<{0}> ({1}); }}",
base.CSType, StudlyName + "Ptr"); base.CSType, studly_name + "Ptr");
if (Writable) if (Writable)
sw.WriteLine (indent + "\tset {{ {0} = GLib.Marshaller.StructArrayToNullTerminatedStructArrayIntPtr<{1}> (value); }}", sw.WriteLine (indent + "\tset {{ {0} = GLib.Marshaller.StructArrayToNullTerminatedStructArrayIntPtr<{1}> (value); }}",
StudlyName + "Ptr", base.CSType); studly_name + "Ptr", base.CSType);
sw.WriteLine (indent + "}"); sw.WriteLine (indent + "}");
} }
} else if (IsBitfield) { } else if (IsBitfield) {
base.Generate (gen_info, indent); base.Generate (gen_info, indent);
} else if (gen is IAccessor) { } else if (gen is IAccessor) {
sw.WriteLine (indent + "private {0} {1};", gen.MarshalType, Name); sw.WriteLine (indent + "private {0} {1};", gen.MarshalType, name);
if (Access != "private") { if (Access != "private") {
IAccessor acc = table [CType] as IAccessor; IAccessor acc = table [CType] as IAccessor;
sw.WriteLine (indent + Access + " " + wrapped + " " + StudlyName + " {"); sw.WriteLine (indent + Access + " " + wrapped + " " + studly_name + " {");
acc.WriteAccessors (sw, indent + "\t", Name); acc.WriteAccessors (sw, indent + "\t", name);
sw.WriteLine (indent + "}"); sw.WriteLine (indent + "}");
} }
} else if (IsPointer && (gen is StructGen || gen is BoxedGen || gen is UnionGen)) { } else if (IsPointer && (gen is StructGen || gen is BoxedGen || gen is UnionGen)) {
sw.WriteLine (indent + "private {0} {1};", CSType, Name); sw.WriteLine (indent + "private {0} {1};", cstype, name);
sw.WriteLine (); sw.WriteLine ();
if (Access != "private") { if (Access != "private") {
sw.WriteLine (indent + Access + " " + wrapped + " " + wrapped_name + " {"); sw.WriteLine (indent + Access + " " + wrapped + " " + wrapped_name + " {");
sw.WriteLine (indent + "\tget { return " + table.FromNative (CType, Name) + "; }"); sw.WriteLine (indent + "\tget { return " + table.FromNative (CType, name) + "; }");
sw.WriteLine (indent + "}"); sw.WriteLine (indent + "}");
} }
} else if (IsPointer && CSType != "string") { } else if (IsPointer && cstype != "string") {
// FIXME: probably some fields here which should be visible. // FIXME: probably some fields here which should be visible.
visible = false; visible = false;
sw.WriteLine (indent + "private {0} {1};", CSType, Name); sw.WriteLine (indent + "private {0} {1};", cstype, name);
} else { } else {
sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, Access == "public" ? StudlyName : Name); sw.WriteLine (indent + "{0} {1} {2};", Access, cstype, Access == "public" ? studly_name : name);
} }
} }
} }
} }

View file

@ -35,7 +35,6 @@ namespace GtkSharp.Generation {
StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name, NS); StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name, NS);
base.Generate (gen_info); base.Generate (gen_info);
GenerateStructureABI(gen_info);
if (GetMethod ("GetType") == null && GetMethod ("GetGType") == null) { if (GetMethod ("GetType") == null && GetMethod ("GetGType") == null) {
sw.WriteLine ("\t\tprivate static GLib.GType GType {"); sw.WriteLine ("\t\tprivate static GLib.GType GType {");
sw.WriteLine ("\t\t\tget { return GLib.GType.Pointer; }"); sw.WriteLine ("\t\t\tget { return GLib.GType.Pointer; }");

View file

@ -128,9 +128,17 @@ namespace GtkSharp.Generation {
AddType (new ManualGen ("GVariant", "GLib.Variant")); AddType (new ManualGen ("GVariant", "GLib.Variant"));
AddType (new ManualGen ("GVariantType", "GLib.VariantType")); AddType (new ManualGen ("GVariantType", "GLib.VariantType"));
AddType (new ManualGen ("GValueArray", "GLib.ValueArray")); AddType (new ManualGen ("GValueArray", "GLib.ValueArray"));
AddType (new ManualGen ("GMutex", "GLib.Mutex")); AddType (new ManualGen ("GMutex", "GLib.Mutex",
AddType (new ManualGen ("GRecMutex", "GLib.RecMutex")); "new GLib.Mutex({0})",
AddType (new ManualGen ("GCond", "GLib.Cond")); "GLib.Mutex.ABI"));
AddType (new ManualGen ("GRecMutex",
"GLib.RecMutex",
"new GLib.RecMutex({0})",
"GLib.RecMutex.ABI"));
AddType (new ManualGen ("GCond", "GLib.Cond",
"new GLib.Cond({0})",
"GLib.Cond.ABI"));
AddType (new ManualGen ("GDateTime", "GLib.DateTime")); AddType (new ManualGen ("GDateTime", "GLib.DateTime"));
AddType (new ManualGen ("GDate", "GLib.Date")); AddType (new ManualGen ("GDate", "GLib.Date"));
AddType (new ManualGen ("GSource", "GLib.Source")); AddType (new ManualGen ("GSource", "GLib.Source"));
@ -141,9 +149,12 @@ namespace GtkSharp.Generation {
AddType (new MarshalGen ("GString", "string", "IntPtr", "new GLib.GString ({0}).Handle", "GLib.GString.PtrToString ({0})")); AddType (new MarshalGen ("GString", "string", "IntPtr", "new GLib.GString ({0}).Handle", "GLib.GString.PtrToString ({0})"));
AddType (new MarshalGen ("GType", "GLib.GType", "IntPtr", "{0}.Val", "new GLib.GType({0})", "GLib.GType.None")); AddType (new MarshalGen ("GType", "GLib.GType", "IntPtr", "{0}.Val", "new GLib.GType({0})", "GLib.GType.None"));
AddType (new ByRefGen ("GValue", "GLib.Value")); AddType (new ByRefGen ("GValue", "GLib.Value"));
AddType (new SimpleGen ("GDestroyNotify", "GLib.DestroyNotify", "null")); AddType (new SimpleGen ("GDestroyNotify", "GLib.DestroyNotify", "null",
"(uint) Marshal.SizeOf(typeof(IntPtr))"));
AddType (new SimpleGen ("GThread", "GLib.Thread", "null")); AddType (new SimpleGen ("GThread", "GLib.Thread", "null"));
AddType (new ManualGen ("GBytes", "GLib.Bytes")); AddType (new ManualGen ("GBytes", "GLib.Bytes"));
AddType (new SimpleGen ("GHookList", "GLib.HookList", "null",
"GLib.HookList.abi_info.Size"));
// FIXME: These ought to be handled properly. // FIXME: These ought to be handled properly.
AddType (new SimpleGen ("GC", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GC", "IntPtr", "IntPtr.Zero"));
@ -160,6 +171,9 @@ namespace GtkSharp.Generation {
AddType (new SimpleGen ("va_list", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("va_list", "IntPtr", "IntPtr.Zero"));
AddType (new SimpleGen ("GParamSpec", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("GParamSpec", "IntPtr", "IntPtr.Zero"));
AddType (new SimpleGen ("gconstpointer", "IntPtr", "IntPtr.Zero")); AddType (new SimpleGen ("gconstpointer", "IntPtr", "IntPtr.Zero"));
AddType (new SimpleGen ("GBoxedCopyFunc", "IntPtr", "IntPtr.Zero"));
AddType (new SimpleGen ("GBoxedFreeFunc", "IntPtr", "IntPtr.Zero"));
AddType (new SimpleGen ("GHookFinalizeFunc", "IntPtr", "IntPtr.Zero"));
} }
public void AddType (IGeneratable gen) public void AddType (IGeneratable gen)
@ -252,7 +266,7 @@ namespace GtkSharp.Generation {
IGeneratable gen = this[c_type]; IGeneratable gen = this[c_type];
if (gen == null) { if (gen == null) {
if (c_type.EndsWith("*") && default_pointer) if (c_type.EndsWith("*") && default_pointer)
return "UintPtr"; return "IntPtr";
return ""; return "";
} }

View file

@ -33,27 +33,66 @@ namespace GtkSharp.Generation {
} }
} }
public void Generate(GenerationInfo gen_info, string indent){ public string GenerateGetSize(string indent) {
var size = indent += "new List<string>() {";
var is_first = true;
foreach (StructABIField field in fields) {
if (!is_first)
size += ",";
is_first = false;
size += "\"" + field.CName + "\"";
}
return size + "}";
}
public void EnsureParentStructName (string parent_name) {
var name = Elem.GetAttribute("name");
if (!unique_field) {
parent_name = parent_name + '.' + name;
}
StructABIField next_field = null;
foreach (var field in fields) {
field.parent_structure_name = parent_name;
}
}
public StructField Generate(GenerationInfo gen_info, string indent,
string parent_name, StructABIField prev_field,
StructABIField next, string struct_parent_name,
TextWriter tw)
{
StreamWriter sw = gen_info.Writer; StreamWriter sw = gen_info.Writer;
var name = Elem.GetAttribute("name"); var name = Elem.GetAttribute("name");
var cname = Elem.GetAttribute("cname"); var cname = Elem.GetAttribute("cname");
if (unique_field) { if (!unique_field) {
sw.WriteLine (indent + "[FieldOffset(0)]"); parent_name = parent_name + '.' + name;
foreach (StructABIField field in fields)
field.Generate(gen_info, indent);
return;
} }
sw.WriteLine (indent + "struct __" + name + "{"); StructABIField next_field = null;
foreach (StructABIField field in fields) { sw.WriteLine(indent + "// union struct " + parent_name);
field.Generate(gen_info, indent + "\t"); for(int i=0; i < fields.Count; i++) {
var field = fields[i];
next_field = fields.Count > i + 1 ? fields[i + 1] : null;
field.parent_structure_name = parent_name;
field.Generate(gen_info, indent, prev_field, next_field, struct_parent_name,
tw);
prev_field = field;
} }
sw.WriteLine (indent + "}");
sw.WriteLine (indent + "[FieldOffset(0)]"); sw.WriteLine(indent + "// End " + parent_name);
sw.WriteLine (indent + "private __" + name + " " + cname + ";"); sw.WriteLine();
return prev_field;
} }
} }
public class UnionABIField : StructABIField { public class UnionABIField : StructABIField {
@ -70,18 +109,41 @@ namespace GtkSharp.Generation {
} }
} }
public override void Generate (GenerationInfo gen_info, string indent) { public override StructABIField Generate (GenerationInfo gen_info, string indent,
StructABIField prev_field, StructABIField next_field, string parent_name,
TextWriter tw) {
StreamWriter sw = gen_info.Writer; StreamWriter sw = gen_info.Writer;
var name = Elem.GetAttribute("name"); var name = Elem.GetAttribute("name");
var cname = Elem.GetAttribute("cname"); var cname = Elem.GetAttribute("cname");
sw.WriteLine (indent + "[StructLayout(LayoutKind.Explicit)]"); foreach (UnionSubstruct _struct in substructs)
sw.WriteLine (indent + "struct __" + name + " {"); _struct.EnsureParentStructName(cname);
foreach (UnionSubstruct _struct in substructs) { foreach (UnionSubstruct _struct in substructs) {
_struct.Generate(gen_info, indent + "\t"); _struct.Generate(gen_info, indent + "\t", cname, prev_field,
next_field, parent_name, tw);
} }
sw.WriteLine (indent + "}");
sw.WriteLine (indent + "private __" + name + " " + cname + ";"); base.Generate(gen_info, indent, prev_field, next_field, parent_name, null);
return this;
}
public override string GenerateGetSizeOf(string indent) {
string res = indent + "new List<List<string>>() { // union " + Elem.GetAttribute("cname") + "\n";
bool first = true;
indent += "\t\t\t";
foreach (UnionSubstruct _struct in substructs) {
if (!first)
res += ",\n";
first = false;
res += _struct.GenerateGetSize(indent + "\t\t\t");
}
res += "\n" + indent + "\t\t }";
return res;
} }
public override bool Validate (LogWriter log) public override bool Validate (LogWriter log)

177
Source/glib/AbiField.cs Normal file
View file

@ -0,0 +1,177 @@
// AbiField.cs - Utility to handle complex C structure ABI.
//
// Authors: Thibault Saunier <thibault.saunier@osg.samsung.com>
//
// Copyright (c) 2017 Thibault Saunier
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the Lesser GNU General
// Public License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// Helper utility to build C structure ABI even when using complex
// packing with union and bit fields. It basically uses the same
// logic as what is done inside csharp implementation (marshal.c in
// the mono codebase) but handling more things.
namespace GLib {
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Linq;
using System.Collections.Specialized;
using System.CodeDom.Compiler;
public class AbiField {
public string Prev_name;
public string Next_name;
public string Name;
public long Offset;
public long Align;
public uint Natural_size;
public AbiStruct container;
public OrderedDictionary Parent_fields; // field_name<string> -> AbiField<> dictionary.
List<List<string>> Union_fields;
long End;
long Size;
public uint Bits;
public AbiField(string name,
long offset,
uint natural_size,
string prev_fieldname,
string next_fieldname,
long align,
uint bits)
{
Name = name;
Offset = offset;
Natural_size = natural_size;
Prev_name = prev_fieldname;
Next_name = next_fieldname;
End = -1;
Size = -1;
Union_fields = null;
Align = (long) align;
Bits = bits;
if (Bits > 0) {
var nbytes = (uint) (Math.Ceiling((double) Bits / (double) 8));
if (nbytes < GetSize())
Align = 1;
else // Like if no bitfields were used.
Bits = 0;
}
}
public AbiField(string name,
OrderedDictionary parent_fields,
uint natural_size,
string prev_fieldname,
string next_fieldname,
long align,
uint bits): this (name, -1,
natural_size, prev_fieldname, next_fieldname, align, bits)
{
Parent_fields = parent_fields;
}
public AbiField(string name,
long offset,
List<List<string>> fields_lists,
string prev_fieldname,
string next_fieldname, uint bits): this(name,
offset, (uint) 0, prev_fieldname, next_fieldname,
-1, bits)
{
Union_fields = fields_lists;
}
public uint GetEnd() {
if (End == -1)
End = (long) GetOffset() + GetSize();
return (uint) End;
}
public uint GetOffset() {
return (uint) Offset;
}
public bool InUnion () {
return Name.Contains(".");
}
public uint GetAlign () {
if (Union_fields != null) {
uint align = 1;
foreach (var fieldnames in Union_fields) {
foreach (var fieldname in fieldnames) {
var field = (AbiField) container.Fields[fieldname];
align = Math.Max(align, field.GetAlign());
}
}
return align;
}
return (uint) Align;
}
public uint GetUnionSize() {
uint size = 0;
foreach (var fieldnames in Union_fields) {
foreach (var fieldname in fieldnames) {
var field = ((AbiField) container.Fields[fieldname]);
var align = field.GetAlign();
if (field.Prev_name != null) {
var prev = ((AbiField)container.Fields[field.Prev_name]);
if (!prev.InUnion())
field.Offset = Offset;
else
field.Offset = prev.GetEnd();
}
field.Offset += align - 1;
field.Offset &= ~(align - 1);
size = Math.Max(size, field.GetEnd() - (uint) Offset);
}
}
return size;
}
public uint GetSize() {
if (Size != -1)
return (uint) Size;
if (Union_fields != null) {
Size = GetUnionSize();
} else {
Size = Natural_size;
}
return (uint) Size;
}
}
}

142
Source/glib/AbiStruct.cs Normal file
View file

@ -0,0 +1,142 @@
// AbiField.cs - Utility to handle complex C structure ABI.
//
// Authors: Thibault Saunier <thibault.saunier@osg.samsung.com>
//
// Copyright (c) 2017 Thibault Saunier
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the Lesser GNU General
// Public License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// Helper utility to build C structure ABI even when using complex
// packing with union and bit fields. It basically uses the same
// logic as what is done inside csharp implementation (marshal.c in
// the mono codebase) but handling more things.
namespace GLib {
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Linq;
using System.Collections.Specialized;
using System.CodeDom.Compiler;
public class AbiStruct {
public OrderedDictionary Fields = null;
public AbiStruct(List<GLib.AbiField> fields) {
Fields = new OrderedDictionary();
foreach (var field in fields)
Fields[field.Name] = field;
Load();
}
static uint GetMinAlign(OrderedDictionary fields) {
uint align = 1;
for (var i = 0; i < fields.Count; i++) {
var field = ((GLib.AbiField) fields[i]);
if (field.Parent_fields != null) {
align = Math.Max(align, GetMinAlign(field.Parent_fields));
}
align = Math.Max(align, field.GetAlign());
}
return align;
}
public uint Align {
get {
return GetMinAlign(Fields);
}
}
void Load () {
long bitfields_offset = -1;
long bitfields_size = -1;
for (var i = 0; i < Fields.Count; i++ ) {
var field = (AbiField) Fields[i];
field.container = this;
var align = field.GetAlign();
if (field.InUnion())
continue;
if (field.Prev_name != null) {
field.Offset = ((AbiField)Fields[field.Prev_name]).GetEnd();
} else if (field.Parent_fields != null) {
field.Offset = GetStructureSize(field.Parent_fields);
}
field.Offset += align - 1;
field.Offset &= ~(align - 1);
if (field.Bits > 0) {
// Pack all following bitfields into the same area.
if (bitfields_offset == -1) {
uint nbits = 0;
bitfields_offset = field.Offset;
for (var j = i + 1; j < Fields.Count; j++ ) {
var nfield = (AbiField) Fields[j];
if (nfield.Bits > 0)
nbits += nfield.Bits;
}
bitfields_size = (long) (Math.Ceiling((double) field.Bits / (double) 8));
}
field.Offset = (uint) bitfields_offset;
field.Natural_size = (uint) bitfields_size;
} else {
bitfields_offset = bitfields_size = -1;
}
}
}
public uint GetFieldOffset(string field) {
return ((AbiField) Fields[field]).GetOffset();
}
static uint GetStructureSize(OrderedDictionary fields) {
uint size = 0;
uint min_align = GetMinAlign(fields);
for (var i = 0; i < fields.Count; i++) {
var field = ((GLib.AbiField) fields[i]);
if (field.InUnion())
continue;
var tsize = (uint) (Math.Ceiling((double) (field.GetEnd() / (double) min_align)) * (double) min_align);
size = Math.Max(tsize, size);
}
return size;
}
public uint Size {
get {
return GetStructureSize(Fields);
}
}
}
}

View file

@ -10,6 +10,11 @@ namespace GLib {
#region Autogenerated code #region Autogenerated code
public partial class Cond : GLib.Opaque { public partial class Cond : GLib.Opaque {
public struct ABI {
IntPtr p;
int i1;
int i2;
}
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
static extern void g_cond_broadcast(IntPtr raw); static extern void g_cond_broadcast(IntPtr raw);

114
Source/glib/HookList.cs Normal file
View file

@ -0,0 +1,114 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace GLib {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
#region Autogenerated code
public partial class HookList : GLib.Opaque {
// Internal representation of the wrapped ABI structure.
static public AbiStruct abi_info = new AbiStruct(new List<AbiField> {
new GLib.AbiField("seq_id"
, 0
, (uint) Marshal.SizeOf(typeof(ulong)) // seq_id
, null
, "hook_size"
, (long) Marshal.OffsetOf(typeof(GHookList_seq_idAlign), "seq_id")
, 0
),
new GLib.AbiField("hook_size"
, -1
, (uint) Marshal.SizeOf(typeof(uint)) // hook_size
, "seq_id"
, "is_setup"
, 1
, 16
),
new GLib.AbiField("is_setup"
, -1
, (uint) Marshal.SizeOf(typeof(bool)) // is_setup
, "hook_size"
, "hooks"
, 1
, 1
),
new GLib.AbiField("hooks"
, -1
, (uint) Marshal.SizeOf(typeof(IntPtr)) // hooks
, "is_setup"
, "dummy3"
, (long) Marshal.OffsetOf(typeof(GHookList_hooksAlign), "hooks")
, 0
),
new GLib.AbiField("dummy3"
, -1
, (uint) Marshal.SizeOf(typeof(IntPtr)) // dummy3
, "hooks"
, "finalize_hook"
, (long) Marshal.OffsetOf(typeof(GHookList_dummy3Align), "dummy3")
, 0
),
new GLib.AbiField("finalize_hook"
, -1
, (uint) Marshal.SizeOf(typeof(IntPtr)) // finalize_hook
, "dummy3"
, "dummy"
, (long) Marshal.OffsetOf(typeof(GHookList_finalize_hookAlign), "finalize_hook")
, 0
),
new GLib.AbiField("dummy"
, -1
, (uint) Marshal.SizeOf(typeof(IntPtr)) * 2 // dummy
, "finalize_hook"
, null
, (long) Marshal.OffsetOf(typeof(GHookList_dummyAlign), "dummy")
, 0
)
}
);
[StructLayout(LayoutKind.Sequential)]
public struct GHookList_seq_idAlign
{
sbyte f1;
private UIntPtr seq_id;
}
[StructLayout(LayoutKind.Sequential)]
public struct GHookList_hooksAlign
{
sbyte f1;
private IntPtr hooks;
}
[StructLayout(LayoutKind.Sequential)]
public struct GHookList_dummy3Align
{
sbyte f1;
private IntPtr dummy3;
}
[StructLayout(LayoutKind.Sequential)]
public struct GHookList_finalize_hookAlign
{
sbyte f1;
private IntPtr finalize_hook;
}
[StructLayout(LayoutKind.Sequential)]
public struct GHookList_dummyAlign
{
sbyte f1;
[MarshalAs (UnmanagedType.ByValArray, SizeConst=2)]
private IntPtr[] dummy;
}
// End of the ABI representation.
#endregion
}
}

View file

@ -10,6 +10,11 @@ namespace GLib {
#region Autogenerated code #region Autogenerated code
public partial class Mutex : GLib.Opaque { public partial class Mutex : GLib.Opaque {
public struct ABI {
IntPtr p;
int i1;
int i2;
}
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
static extern void g_mutex_clear(IntPtr raw); static extern void g_mutex_clear(IntPtr raw);

View file

@ -823,8 +823,6 @@ namespace GLib {
public IntPtr g_class; public IntPtr g_class;
} }
public static uint instance_offset { get { return 0; }}
public uint GetFieldOffset(string field) { throw new NotImplementedException(); return 0; }
public struct GObject { public struct GObject {
public GTypeInstance type_instance; public GTypeInstance type_instance;
public uint ref_count; public uint ref_count;
@ -848,5 +846,56 @@ namespace GLib {
if (Environment.GetEnvironmentVariable ("GTK_SHARP_DEBUG") != null) if (Environment.GetEnvironmentVariable ("GTK_SHARP_DEBUG") != null)
GLib.Log.SetLogHandler ("GLib-GObject", GLib.LogLevelFlags.All, new GLib.LogFunc (GLib.Log.PrintTraceLogFunction)); GLib.Log.SetLogHandler ("GLib-GObject", GLib.LogLevelFlags.All, new GLib.LogFunc (GLib.Log.PrintTraceLogFunction));
} }
// Internal representation of the wrapped ABI structure.
static public AbiStruct abi_info = new AbiStruct(new List<AbiField> {
new GLib.AbiField("g_type_instance"
, 0
, (uint) Marshal.SizeOf(typeof(IntPtr)) // g_type_instance
, null
, "ref_count"
, (long) Marshal.OffsetOf(typeof(GObject_g_type_instanceAlign), "g_type_instance")
, 0
),
new GLib.AbiField("ref_count"
, -1
, (uint) Marshal.SizeOf(typeof(uint)) // ref_count
, "g_type_instance"
, "qdata"
, (long) Marshal.OffsetOf(typeof(GObject_ref_countAlign), "ref_count")
, 0
),
new GLib.AbiField("qdata"
, -1
, (uint) Marshal.SizeOf(typeof(IntPtr)) // qdata
, "ref_count"
, null
, (long) Marshal.OffsetOf(typeof(GObject_qdataAlign), "qdata")
, 0
),
}
);
[StructLayout(LayoutKind.Sequential)]
public struct GObject_g_type_instanceAlign
{
sbyte f1;
private IntPtr g_type_instance;
}
[StructLayout(LayoutKind.Sequential)]
public struct GObject_ref_countAlign
{
sbyte f1;
private uint ref_count;
}
[StructLayout(LayoutKind.Sequential)]
public struct GObject_qdataAlign
{
sbyte f1;
private IntPtr qdata;
}
// End of the ABI representation.
} }
} }

View file

@ -10,6 +10,13 @@ namespace GLib {
#region Autogenerated code #region Autogenerated code
public partial class RecMutex : GLib.Opaque { public partial class RecMutex : GLib.Opaque {
[StructLayout(LayoutKind.Sequential)]
public struct ABI {
IntPtr p;
int i1;
int i2;
}
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
static extern void g_rec_mutex_clear(IntPtr raw); static extern void g_rec_mutex_clear(IntPtr raw);

View file

@ -21,6 +21,8 @@ policy = configure_file(input: policy_config,
configuration : policy_data) configuration : policy_data)
sources = [ sources = [
'AbiField.cs',
'AbiStruct.cs',
'Argv.cs', 'Argv.cs',
'Bytes.cs', 'Bytes.cs',
'ConnectBeforeAttribute.cs', 'ConnectBeforeAttribute.cs',
@ -39,6 +41,7 @@ sources = [
'GString.cs', 'GString.cs',
'GType.cs', 'GType.cs',
'GTypeAttribute.cs', 'GTypeAttribute.cs',
'HookList.cs',
'Idle.cs', 'Idle.cs',
'InitiallyUnowned.cs', 'InitiallyUnowned.cs',
'IOChannel.cs', 'IOChannel.cs',