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:
parent
7d902ef7e4
commit
248278d267
28 changed files with 1011 additions and 115 deletions
|
@ -71,7 +71,7 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
|
||||
protected ClassBase (XmlElement ns, XmlElement elem) : base (ns, elem) {
|
||||
|
||||
|
||||
deprecated = elem.GetAttributeAsBoolean ("deprecated");
|
||||
isabstract = elem.GetAttributeAsBoolean ("abstract");
|
||||
abi_fields_valid = true;
|
||||
|
@ -147,7 +147,7 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
protected virtual bool CanGenerateABIStruct(LogWriter log) {
|
||||
public virtual bool CanGenerateABIStruct(LogWriter log) {
|
||||
return (abi_fields_valid);
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ namespace GtkSharp.Generation {
|
|||
if (parent != null) {
|
||||
// FIXME Add that information to ManualGen and use it.
|
||||
if (parent.CName == "GInitiallyUnowned" || parent.CName == "GObject") {
|
||||
cs_parent_struct = "GLib.Object.GObject";
|
||||
cs_parent_struct = "GLib.Object";
|
||||
} else {
|
||||
parent_can_generate = false;
|
||||
var _parent = parent as ClassBase;
|
||||
|
@ -175,9 +175,8 @@ namespace GtkSharp.Generation {
|
|||
parent_can_generate = _parent.CheckABIStructParent(log, out tmp);
|
||||
}
|
||||
|
||||
if (parent_can_generate) {
|
||||
cs_parent_struct = cs_parent + "._" + parent.CName + "ABI";
|
||||
}
|
||||
if (parent_can_generate)
|
||||
cs_parent_struct = cs_parent;
|
||||
}
|
||||
|
||||
if (!parent_can_generate) {
|
||||
|
@ -191,16 +190,6 @@ namespace GtkSharp.Generation {
|
|||
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)
|
||||
{
|
||||
string cs_parent_struct = null;
|
||||
|
@ -213,21 +202,54 @@ namespace GtkSharp.Generation {
|
|||
|
||||
var _new = "";
|
||||
if (cs_parent_struct != "")
|
||||
_new = "new";
|
||||
_new = "new ";
|
||||
|
||||
WriteInstanceOffsetMethod(sw, cs_parent_struct);
|
||||
sw.WriteLine ();
|
||||
sw.WriteLine ("\t\tpublic " + _new + " unsafe uint GetFieldOffset(string field) {");
|
||||
sw.WriteLine ("\t\t\treturn (uint) (instance_offset + (uint) Marshal.OffsetOf(typeof({0}), field));",
|
||||
(QualifiedName + "._" + CName + "ABI"));
|
||||
sw.WriteLine ("\t\t// Internal representation of the wrapped structure ABI.");
|
||||
sw.WriteLine ("\t\tstatic GLib.AbiStruct _abi_info = null;");
|
||||
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 ();
|
||||
|
||||
sw.WriteLine ("\t\t[StructLayout (LayoutKind.Sequential)]");
|
||||
sw.WriteLine ("\t\tpublic struct _" + CName + "ABI" + " {");
|
||||
foreach (StructABIField field in abi_fields)
|
||||
field.Generate (gen_info, "\t\t\t");
|
||||
sw.WriteLine ("\t\t}");
|
||||
sw.WriteLine (field_alignment_structures_writer.ToString());
|
||||
sw.WriteLine ("\t\t// End of the ABI representation.");
|
||||
sw.WriteLine ();
|
||||
}
|
||||
|
||||
|
@ -251,6 +273,10 @@ namespace GtkSharp.Generation {
|
|||
if (!abi_field.Validate(log))
|
||||
abi_fields_valid = false;
|
||||
}
|
||||
if (abi_fields_valid)
|
||||
foreach (StructABIField abi_field in abi_fields) {
|
||||
abi_field.SetGetOffseName();
|
||||
}
|
||||
|
||||
ArrayList invalids = new ArrayList ();
|
||||
|
||||
|
@ -348,8 +374,9 @@ namespace GtkSharp.Generation {
|
|||
|
||||
protected void GenFields (GenerationInfo gen_info)
|
||||
{
|
||||
foreach (ObjectField field in fields.Values)
|
||||
foreach (ObjectField field in fields.Values) {
|
||||
field.Generate (gen_info, "\t\t");
|
||||
}
|
||||
}
|
||||
|
||||
protected void GenConstants (GenerationInfo gen_info)
|
||||
|
@ -391,7 +418,7 @@ namespace GtkSharp.Generation {
|
|||
|
||||
foreach (Method method in methods.Values) {
|
||||
if (IgnoreMethod (method, implementor))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
string oname = null, oprotection = null;
|
||||
if (collisions != null && collisions.ContainsKey (method.Name)) {
|
||||
|
|
|
@ -34,9 +34,13 @@ namespace GtkSharp.Generation {
|
|||
public static int Main (string[] args)
|
||||
{
|
||||
bool show_help = false;
|
||||
bool all_opaque = true;
|
||||
string dir = "";
|
||||
string assembly_name = "";
|
||||
string gapidir = "";
|
||||
string abi_cs_usings = "";
|
||||
string abi_cs_file = "";
|
||||
string abi_c_file = "";
|
||||
string glue_filename = "";
|
||||
string glue_includes = "";
|
||||
string gluelib_name = "";
|
||||
|
@ -59,6 +63,12 @@ namespace GtkSharp.Generation {
|
|||
(string v) => { assembly_name = v; } },
|
||||
{ "gapidir=", "GAPI xml data folder.",
|
||||
(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.",
|
||||
(string v) => { glue_filename = v; } },
|
||||
{ "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;
|
||||
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) {
|
||||
if (gen_info == null)
|
||||
|
@ -142,7 +153,7 @@ namespace GtkSharp.Generation {
|
|||
ObjectGen.GenerateMappers ();
|
||||
|
||||
if (gen_info != null)
|
||||
gen_info.CloseGlueWriter ();
|
||||
gen_info.CloseWriters ();
|
||||
|
||||
Statistics.Report();
|
||||
return 0;
|
||||
|
|
|
@ -82,6 +82,11 @@ namespace GtkSharp.Generation {
|
|||
{
|
||||
return "(" + QualifiedName + ") " + var;
|
||||
}
|
||||
|
||||
public override string GenerateAlign () {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public override void Generate (GenerationInfo gen_info)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,8 @@ namespace GtkSharp.Generation {
|
|||
|
||||
public abstract class FieldBase : PropertyBase {
|
||||
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, FieldBase abi_field) : base (elem, container_type) {
|
||||
|
@ -97,13 +99,13 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
|
||||
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 &&
|
||||
gen_info.GlueWriter == null);
|
||||
}
|
||||
|
||||
string getterName, setterName;
|
||||
protected string getOffsetName, offsetName;
|
||||
|
||||
void CheckGlue (GenerationInfo gen_info)
|
||||
{
|
||||
getterName = setterName = getOffsetName = null;
|
||||
|
@ -112,7 +114,7 @@ namespace GtkSharp.Generation {
|
|||
|
||||
if (UseABIStruct(gen_info)) {
|
||||
getOffsetName = abi_field.getOffsetName;
|
||||
offsetName = "GetFieldOffset(\"" + ((StructField)abi_field).EqualityName + "\")";
|
||||
offsetName = "abi_info.GetFieldOffset(\"" + ((StructField)abi_field).CName + "\")";
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,14 @@ namespace GtkSharp.Generation {
|
|||
|
||||
public abstract bool Validate ();
|
||||
|
||||
public virtual string GenerateGetSizeOf () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual string GenerateAlign () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Generate ()
|
||||
{
|
||||
GenerationInfo geninfo = new GenerationInfo (ns);
|
||||
|
|
|
@ -33,7 +33,11 @@ namespace GtkSharp.Generation {
|
|||
string gluelib_name;
|
||||
bool glue_enabled;
|
||||
StreamWriter sw;
|
||||
StreamWriter abiwriter = null;
|
||||
StreamWriter cabiwriter = null;
|
||||
StreamWriter glue_sw;
|
||||
string abicfile = null;
|
||||
string abicsfile = null;
|
||||
|
||||
public GenerationInfo (XmlElement ns)
|
||||
{
|
||||
|
@ -43,17 +47,23 @@ namespace GtkSharp.Generation {
|
|||
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.assembly_name = assembly_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) {
|
||||
FileStream stream;
|
||||
|
@ -79,6 +89,44 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
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 {
|
||||
|
@ -87,6 +135,18 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
public StreamWriter AbiWriter {
|
||||
get {
|
||||
return abiwriter;
|
||||
}
|
||||
}
|
||||
|
||||
public StreamWriter CAbiWriter {
|
||||
get {
|
||||
return cabiwriter;
|
||||
}
|
||||
}
|
||||
|
||||
public string Dir {
|
||||
get {
|
||||
return dir;
|
||||
|
@ -120,10 +180,22 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
public void CloseGlueWriter ()
|
||||
public void CloseWriters ()
|
||||
{
|
||||
if (glue_sw != null)
|
||||
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;
|
||||
|
|
|
@ -48,6 +48,12 @@ namespace GtkSharp.Generation {
|
|||
// Generates an expression to convert var from MarshalType
|
||||
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 ();
|
||||
|
||||
void Generate ();
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace GtkSharp.Generation {
|
|||
public class ManualGen : SimpleBase {
|
||||
|
||||
string from_fmt;
|
||||
string abi_type;
|
||||
|
||||
public ManualGen (string ctype, string type) : base (ctype, type, "null")
|
||||
{
|
||||
|
@ -37,13 +38,25 @@ namespace GtkSharp.Generation {
|
|||
{
|
||||
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 {
|
||||
get {
|
||||
return "IntPtr";
|
||||
}
|
||||
}
|
||||
|
||||
public string AbiType {
|
||||
get {
|
||||
return abi_type;
|
||||
}
|
||||
}
|
||||
|
||||
public override string CallByName (string var_name)
|
||||
{
|
||||
return var_name + " == null ? IntPtr.Zero : " + var_name + ".Handle";
|
||||
|
@ -53,6 +66,10 @@ namespace GtkSharp.Generation {
|
|||
{
|
||||
return String.Format (from_fmt, var);
|
||||
}
|
||||
|
||||
public override string GenerateGetSizeOf () {
|
||||
return "(uint) Marshal.SizeOf(typeof(" + abi_type + "))";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
protected override bool CanGenerateABIStruct(LogWriter log) {
|
||||
public override bool CanGenerateABIStruct(LogWriter log) {
|
||||
if (!abi_fields_valid) {
|
||||
log.Info(CName + " has invalid fields");
|
||||
|
||||
|
@ -338,5 +338,8 @@ namespace GtkSharp.Generation {
|
|||
|
||||
return true;
|
||||
}
|
||||
public override string GenerateGetSizeOf () {
|
||||
return NS + "." + Name + ".abi_info.GetABISize()";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,7 +175,6 @@ namespace GtkSharp.Generation {
|
|||
sw.WriteLine (" {");
|
||||
sw.WriteLine ();
|
||||
|
||||
GenerateStructureABI (gen_info);
|
||||
GenCtors (gen_info);
|
||||
GenProperties (gen_info, null);
|
||||
GenFields (gen_info);
|
||||
|
@ -248,6 +247,7 @@ namespace GtkSharp.Generation {
|
|||
sw.WriteLine ("\t\t}");
|
||||
}
|
||||
|
||||
GenerateStructureABI (gen_info);
|
||||
sw.WriteLine ("#endregion");
|
||||
|
||||
sw.WriteLine ("\t}");
|
||||
|
@ -426,5 +426,6 @@ namespace GtkSharp.Generation {
|
|||
sw.Close ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ namespace GtkSharp.Generation {
|
|||
sw.WriteLine (" {");
|
||||
sw.WriteLine ();
|
||||
|
||||
GenerateStructureABI(gen_info);
|
||||
GenConstants (gen_info);
|
||||
GenFields (gen_info);
|
||||
GenMethods (gen_info, null, null);
|
||||
|
@ -196,6 +195,7 @@ namespace GtkSharp.Generation {
|
|||
sw.WriteLine ();
|
||||
}
|
||||
|
||||
GenerateStructureABI(gen_info);
|
||||
sw.WriteLine ("#endregion");
|
||||
|
||||
sw.WriteLine ("\t}");
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace GtkSharp.Generation {
|
|||
public abstract class PropertyBase {
|
||||
|
||||
protected XmlElement elem;
|
||||
protected ClassBase container_type;
|
||||
public 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 {
|
||||
return elem.GetAttribute ("cname");
|
||||
}
|
||||
|
|
|
@ -94,6 +94,14 @@ namespace GtkSharp.Generation {
|
|||
public void Generate (GenerationInfo gen_info)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual string GenerateGetSizeOf () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual string GenerateAlign () {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,16 @@ namespace GtkSharp.Generation {
|
|||
using System;
|
||||
|
||||
public class SimpleGen : SimpleBase {
|
||||
public SimpleGen (string ctype, string type, string default_value) : base (ctype, type, default_value) {}
|
||||
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, string size_of) : base (ctype, type, default_value) {
|
||||
this.size_of = size_of;
|
||||
}
|
||||
|
||||
public override string GenerateGetSizeOf () {
|
||||
return size_of;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,14 +7,23 @@ namespace GtkSharp.Generation {
|
|||
|
||||
public class StructABIField : StructField {
|
||||
protected new ClassBase container_type;
|
||||
public string parent_structure_name;
|
||||
|
||||
public StructABIField (XmlElement elem, ClassBase container_type) : base (elem, container_type) {
|
||||
this.container_type = container_type;
|
||||
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) {
|
||||
this.getOffsetName = "Get" + CName + "Offset";
|
||||
base.Generate(gen_info, indent);
|
||||
}
|
||||
|
||||
|
@ -41,20 +50,89 @@ namespace GtkSharp.Generation {
|
|||
|
||||
if (cstype == null || cstype == "") {
|
||||
log.Warn (" field \"" + CName + "\" has no cstype, can't generate ABI field.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!base.Validate (log))
|
||||
return false;
|
||||
|
||||
if (IsBitfield) {
|
||||
log.Warn ("bitfields are not supported");
|
||||
return false;
|
||||
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");
|
||||
}
|
||||
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
get {
|
||||
return QualifiedName + ".Zero";
|
||||
|
@ -134,7 +127,7 @@ namespace GtkSharp.Generation {
|
|||
equals.Append ("true");
|
||||
|
||||
foreach (StructField field in fields) {
|
||||
if (field.IsPadding)
|
||||
if (field.IsPadding || field.Hidden)
|
||||
continue;
|
||||
if (field.IsBitfield) {
|
||||
if (need_field) {
|
||||
|
@ -217,9 +210,16 @@ namespace GtkSharp.Generation {
|
|||
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)
|
||||
{
|
||||
bool need_close = false;
|
||||
|
||||
if (gen_info.Writer == null) {
|
||||
gen_info.Writer = gen_info.OpenStream (Name, NS);
|
||||
need_close = true;
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace GtkSharp.Generation {
|
|||
}
|
||||
}
|
||||
|
||||
int ArrayLength {
|
||||
public int ArrayLength {
|
||||
get {
|
||||
if (!IsArray)
|
||||
return 0;
|
||||
|
@ -50,17 +50,17 @@ namespace GtkSharp.Generation {
|
|||
try {
|
||||
result = Int32.Parse (elem.GetAttribute("array_len"));
|
||||
} catch (Exception) {
|
||||
LogWriter log = new LogWriter (container_type.Name + "." + Name);
|
||||
LogWriter log = new LogWriter (container_type.Name + "." + Name);
|
||||
|
||||
log.Warn("Non-numeric array_len: \"" + elem.GetAttribute("array_len") +
|
||||
"\" incorrectly generated");
|
||||
"\" incorrectly generated");
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsNullTermArray {
|
||||
public bool IsNullTermArray {
|
||||
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 {
|
||||
get {
|
||||
if (elem.GetAttributeAsBoolean ("is-padding"))
|
||||
|
@ -114,7 +162,7 @@ namespace GtkSharp.Generation {
|
|||
|
||||
public bool IsPointer {
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
visible = Access != "private";
|
||||
|
||||
StreamWriter sw = gen_info.Writer;
|
||||
SymbolTable table = SymbolTable.Table;
|
||||
|
||||
string wrapped = table.GetCSType (CType);
|
||||
|
||||
string wrapped_name = SymbolTable.Table.MangleName (CName);
|
||||
string name = Name;
|
||||
string studly_name = StudlyName;
|
||||
string cstype = CSType;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
sw.WriteLine (indent + "private {0} {1};", "IntPtr", StudlyName+ "Ptr");
|
||||
sw.WriteLine (indent + "private {0} {1};", "IntPtr", studly_name+ "Ptr");
|
||||
if ((Readable || Writable) && Access == "public") {
|
||||
sw.WriteLine (indent + "public {0} {1} {{", CSType, StudlyName);
|
||||
sw.WriteLine (indent + "public {0} {1} {{", cstype, studly_name);
|
||||
if (Readable)
|
||||
sw.WriteLine (indent + "\tget {{ return GLib.Marshaller.StructArrayFromNullTerminatedIntPtr<{0}> ({1}); }}",
|
||||
base.CSType, StudlyName + "Ptr");
|
||||
base.CSType, studly_name + "Ptr");
|
||||
if (Writable)
|
||||
sw.WriteLine (indent + "\tset {{ {0} = GLib.Marshaller.StructArrayToNullTerminatedStructArrayIntPtr<{1}> (value); }}",
|
||||
StudlyName + "Ptr", base.CSType);
|
||||
studly_name + "Ptr", base.CSType);
|
||||
sw.WriteLine (indent + "}");
|
||||
}
|
||||
} else if (IsBitfield) {
|
||||
base.Generate (gen_info, indent);
|
||||
} 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") {
|
||||
IAccessor acc = table [CType] as IAccessor;
|
||||
sw.WriteLine (indent + Access + " " + wrapped + " " + StudlyName + " {");
|
||||
acc.WriteAccessors (sw, indent + "\t", Name);
|
||||
sw.WriteLine (indent + Access + " " + wrapped + " " + studly_name + " {");
|
||||
acc.WriteAccessors (sw, indent + "\t", name);
|
||||
sw.WriteLine (indent + "}");
|
||||
}
|
||||
} 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 ();
|
||||
if (Access != "private") {
|
||||
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 + "}");
|
||||
}
|
||||
} else if (IsPointer && CSType != "string") {
|
||||
} else if (IsPointer && cstype != "string") {
|
||||
// FIXME: probably some fields here which should be visible.
|
||||
visible = false;
|
||||
sw.WriteLine (indent + "private {0} {1};", CSType, Name);
|
||||
sw.WriteLine (indent + "private {0} {1};", cstype, name);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace GtkSharp.Generation {
|
|||
|
||||
StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name, NS);
|
||||
base.Generate (gen_info);
|
||||
GenerateStructureABI(gen_info);
|
||||
if (GetMethod ("GetType") == null && GetMethod ("GetGType") == null) {
|
||||
sw.WriteLine ("\t\tprivate static GLib.GType GType {");
|
||||
sw.WriteLine ("\t\t\tget { return GLib.GType.Pointer; }");
|
||||
|
|
|
@ -128,9 +128,17 @@ namespace GtkSharp.Generation {
|
|||
AddType (new ManualGen ("GVariant", "GLib.Variant"));
|
||||
AddType (new ManualGen ("GVariantType", "GLib.VariantType"));
|
||||
AddType (new ManualGen ("GValueArray", "GLib.ValueArray"));
|
||||
AddType (new ManualGen ("GMutex", "GLib.Mutex"));
|
||||
AddType (new ManualGen ("GRecMutex", "GLib.RecMutex"));
|
||||
AddType (new ManualGen ("GCond", "GLib.Cond"));
|
||||
AddType (new ManualGen ("GMutex", "GLib.Mutex",
|
||||
"new GLib.Mutex({0})",
|
||||
"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 ("GDate", "GLib.Date"));
|
||||
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 ("GType", "GLib.GType", "IntPtr", "{0}.Val", "new GLib.GType({0})", "GLib.GType.None"));
|
||||
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 ManualGen ("GBytes", "GLib.Bytes"));
|
||||
AddType (new SimpleGen ("GHookList", "GLib.HookList", "null",
|
||||
"GLib.HookList.abi_info.Size"));
|
||||
|
||||
// FIXME: These ought to be handled properly.
|
||||
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 ("GParamSpec", "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)
|
||||
|
@ -250,19 +264,19 @@ namespace GtkSharp.Generation {
|
|||
public string GetCSType(string c_type, bool default_pointer)
|
||||
{
|
||||
IGeneratable gen = this[c_type];
|
||||
if (gen == null) {
|
||||
if (c_type.EndsWith("*") && default_pointer)
|
||||
return "UintPtr";
|
||||
if (gen == null) {
|
||||
if (c_type.EndsWith("*") && default_pointer)
|
||||
return "IntPtr";
|
||||
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
return gen.QualifiedName;
|
||||
return gen.QualifiedName;
|
||||
}
|
||||
|
||||
public string GetCSType(string c_type)
|
||||
{
|
||||
return GetCSType(c_type, false);
|
||||
return GetCSType(c_type, false);
|
||||
}
|
||||
|
||||
public string GetName(string c_type)
|
||||
|
|
|
@ -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;
|
||||
var name = Elem.GetAttribute("name");
|
||||
var cname = Elem.GetAttribute("cname");
|
||||
|
||||
if (unique_field) {
|
||||
sw.WriteLine (indent + "[FieldOffset(0)]");
|
||||
foreach (StructABIField field in fields)
|
||||
field.Generate(gen_info, indent);
|
||||
|
||||
return;
|
||||
if (!unique_field) {
|
||||
parent_name = parent_name + '.' + name;
|
||||
}
|
||||
|
||||
sw.WriteLine (indent + "struct __" + name + "{");
|
||||
foreach (StructABIField field in fields) {
|
||||
field.Generate(gen_info, indent + "\t");
|
||||
StructABIField next_field = null;
|
||||
sw.WriteLine(indent + "// union struct " + parent_name);
|
||||
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 + "private __" + name + " " + cname + ";");
|
||||
|
||||
sw.WriteLine(indent + "// End " + parent_name);
|
||||
sw.WriteLine();
|
||||
|
||||
return prev_field;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
var name = Elem.GetAttribute("name");
|
||||
var cname = Elem.GetAttribute("cname");
|
||||
|
||||
sw.WriteLine (indent + "[StructLayout(LayoutKind.Explicit)]");
|
||||
sw.WriteLine (indent + "struct __" + name + " {");
|
||||
foreach (UnionSubstruct _struct in substructs)
|
||||
_struct.EnsureParentStructName(cname);
|
||||
|
||||
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)
|
||||
|
|
177
Source/glib/AbiField.cs
Normal file
177
Source/glib/AbiField.cs
Normal 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
142
Source/glib/AbiStruct.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,11 @@ namespace GLib {
|
|||
|
||||
#region Autogenerated code
|
||||
public partial class Cond : GLib.Opaque {
|
||||
public struct ABI {
|
||||
IntPtr p;
|
||||
int i1;
|
||||
int i2;
|
||||
}
|
||||
|
||||
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void g_cond_broadcast(IntPtr raw);
|
||||
|
|
114
Source/glib/HookList.cs
Normal file
114
Source/glib/HookList.cs
Normal 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
|
||||
}
|
||||
}
|
|
@ -10,6 +10,11 @@ namespace GLib {
|
|||
|
||||
#region Autogenerated code
|
||||
public partial class Mutex : GLib.Opaque {
|
||||
public struct ABI {
|
||||
IntPtr p;
|
||||
int i1;
|
||||
int i2;
|
||||
}
|
||||
|
||||
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void g_mutex_clear(IntPtr raw);
|
||||
|
|
|
@ -823,8 +823,6 @@ namespace GLib {
|
|||
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 GTypeInstance type_instance;
|
||||
public uint ref_count;
|
||||
|
@ -848,5 +846,56 @@ namespace GLib {
|
|||
if (Environment.GetEnvironmentVariable ("GTK_SHARP_DEBUG") != null)
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@ namespace GLib {
|
|||
|
||||
#region Autogenerated code
|
||||
public partial class RecMutex : GLib.Opaque {
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ABI {
|
||||
IntPtr p;
|
||||
int i1;
|
||||
int i2;
|
||||
}
|
||||
|
||||
|
||||
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void g_rec_mutex_clear(IntPtr raw);
|
||||
|
|
|
@ -21,6 +21,8 @@ policy = configure_file(input: policy_config,
|
|||
configuration : policy_data)
|
||||
|
||||
sources = [
|
||||
'AbiField.cs',
|
||||
'AbiStruct.cs',
|
||||
'Argv.cs',
|
||||
'Bytes.cs',
|
||||
'ConnectBeforeAttribute.cs',
|
||||
|
@ -39,6 +41,7 @@ sources = [
|
|||
'GString.cs',
|
||||
'GType.cs',
|
||||
'GTypeAttribute.cs',
|
||||
'HookList.cs',
|
||||
'Idle.cs',
|
||||
'InitiallyUnowned.cs',
|
||||
'IOChannel.cs',
|
||||
|
@ -88,7 +91,7 @@ sources = [
|
|||
'ValueArray.cs',
|
||||
'Value.cs',
|
||||
'Variant.cs',
|
||||
'VariantType.cs' ]
|
||||
'VariantType.cs']
|
||||
|
||||
|
||||
glib_sharp = library(assembly_name, sources, assemblyinfo,
|
||||
|
|
Loading…
Reference in a new issue