Bug 551738 - Associate classes with their structs
authorColin Walters <walters@src.gnome.org>
Fri, 6 Feb 2009 18:37:13 +0000 (18:37 +0000)
committerColin Walters <walters@src.gnome.org>
Fri, 6 Feb 2009 18:37:13 +0000 (18:37 +0000)
Inside glibtransformer, we now look at structures ending in "Class" and
see if they have an associated GlibObject (i.e. a structure of the same
name without the "Class" suffix).  If found, pair them up.

The .gir file for <class> gains an attribute denoting its associated
class struct.  Any <record> many now have a glib:is-class-struct-for
annotation which tells which (if any) <class> for which it defines the
layout.

In the .typelib, we record the association between the class and
its structure.  Generic structures however just have a boolean
saying whether they're a class struct.  (Going from a generic class
struct to its class should not be necessary).

Finally, we expose GIRepository APIs to access both bits of information
from the .typelib.

svn path=/trunk/; revision=1088

23 files changed:
docs/typelib-format.txt
girepository/ginfo.c
girepository/girepository.h
girepository/girmodule.c
girepository/girnode.c
girepository/girnode.h
girepository/girparser.c
girepository/gtypelib.c
girepository/gtypelib.h
giscanner/ast.py
giscanner/girwriter.py
giscanner/glibtransformer.py
tests/scanner/BarApp-1.0-expected.gir
tests/scanner/BarApp-1.0-expected.tgir
tests/scanner/annotation-1.0-expected.gir
tests/scanner/annotation-1.0-expected.tgir
tests/scanner/drawable-1.0-expected.gir
tests/scanner/drawable-1.0-expected.tgir
tests/scanner/foo-1.0-expected.gir
tests/scanner/foo-1.0-expected.tgir
tests/scanner/utility-1.0-expected.gir
tests/scanner/utility-1.0-expected.tgir
tools/generate.c

index a47a9f78485352083c03c4137fa95854c481c315..68125cdf91c569310120547cd53c57ac67f117c2 100644 (file)
@@ -1,7 +1,11 @@
 GObject binary typelib for introspection
 -----------------------------------------
 
-Version 0.8
+Version 0.9
+
+Changes since 0.8:
+- Add class struct concept to ObjectBlob
+- Add is_class_struct bit to StructBlob
 
 Changes since 0.7:
 - Add dependencies
@@ -847,7 +851,8 @@ struct StructBlob
   guint        deprecated   : 1;
   guint        unregistered : 1;
   guint        alignment    : 6;
-  guint        reserved     : 8;
+  guint        is_class_struct : 1
+  guint        reserved     : 7;
   guint32      name;
 
   GTypeBlob    gtype;
@@ -866,6 +871,9 @@ unregistered:
 
 alignment:
          The byte boundary that the struct is aligned to in memory
+         
+is_class_struct:
+       Whether this structure is the "class structure" for a GObject
 
 size:    The size of the struct in bytes.
 
@@ -918,7 +926,7 @@ n_values:
 values:   Describes the enum values. 
 
 
-ObjectBlob (32 + x bytes)
+ObjectBlob (36 + x bytes)
 
 struct ObjectBlob
 {
@@ -931,6 +939,7 @@ struct ObjectBlob
   GTypeBlob gtype;
 
   guint16 parent;
+  guint16 class_struct;
 
   guint16 n_interfaces;
   guint16 n_fields;
index 289717d539a5a7e0668d96bb95db120b79c835f9..a51c6cb3ce2522b677c524f2c6523343a1df4aaa 100644 (file)
@@ -1178,6 +1178,24 @@ g_struct_info_get_alignment (GIStructInfo *info)
   return blob->alignment;
 }
 
+/**
+ * g_struct_info_is_class_struct:
+ * @info: GIStructInfo
+ * 
+ * Return true if this structure represents the "class structure" for some
+ * GObject.  This function is mainly useful to hide this kind of structure
+ * from public APIs.
+ *
+ */
+gboolean
+g_struct_info_is_class_struct (GIStructInfo *info)
+{
+  GIBaseInfo *base = (GIBaseInfo *)info;
+  StructBlob *blob = (StructBlob *)&base->typelib->data[base->offset];
+
+  return blob->is_class_struct;
+}
+
 gint
 g_enum_info_get_n_values (GIEnumInfo *info)
 {
@@ -1469,6 +1487,25 @@ g_object_info_get_constant (GIObjectInfo *info,
                                        base->typelib, offset);  
 }
 
+/**
+ * g_object_info_get_class_struct:
+ * @info: A #GIObjectInfo to query
+ * 
+ * Every GObject has two structures; an instance structure and a class
+ * structure.  This function returns the metadata for the class structure.
+ */
+GIStructInfo *
+g_object_info_get_class_struct (GIObjectInfo *info)
+{
+  GIBaseInfo *base = (GIBaseInfo *)info;
+  ObjectBlob *blob = (ObjectBlob *)&base->typelib->data[base->offset];
+
+  if (blob->class_struct)
+    return (GIStructInfo *) g_info_from_entry (base->repository,
+                                               base->typelib, blob->class_struct);
+  else
+    return NULL;
+}
 
 /* GIInterfaceInfo functions */
 gint
index 340c7fa48e8d0a49bb62fd024e7dadb3d9e2d716..ac1b279b0d1dd3a0404ba1391c3262b811c5d944 100644 (file)
@@ -412,6 +412,7 @@ GIFunctionInfo *       g_struct_info_find_method   (GIStructInfo *info,
                                                    const gchar *name);
 gsize                  g_struct_info_get_size      (GIStructInfo *info);
 gsize                  g_struct_info_get_alignment (GIStructInfo *info);
+gboolean               g_struct_info_is_class_struct (GIStructInfo *info);
 
 /* GIRegisteredTypeInfo */
 
@@ -455,6 +456,7 @@ GIVFuncInfo *          g_object_info_get_vfunc              (GIObjectInfo    *in
 gint                   g_object_info_get_n_constants        (GIObjectInfo    *info);
 GIConstantInfo *       g_object_info_get_constant           (GIObjectInfo    *info,
                                                             gint            n);
+GIStructInfo *         g_object_info_get_class_struct       (GIObjectInfo    *info);
 
                                                             
 /* GIInterfaceInfo */
index 85103bff1fdd2b3847040b4bbc9b200b46ff56e2..63d42cceded235e3c62e30342b020fa77b6c0bff 100644 (file)
@@ -223,7 +223,7 @@ g_ir_module_build_typelib (GIrModule  *module,
   header->signature_blob_size = 8;
   header->enum_blob_size = 20;
   header->struct_blob_size = 24;
-  header->object_blob_size = 32;
+  header->object_blob_size = sizeof(ObjectBlob);
   header->interface_blob_size = 28;
   header->union_blob_size = 32;
 
index abec606a3f8b19e2c9d891f25c6f991294e15c64..cc8aa5089b62c6bb176535ee4b113e98a45b9ee1 100644 (file)
@@ -285,7 +285,8 @@ g_ir_node_free (GIrNode *node)
        g_free (node->name);
        g_free (iface->gtype_name);
        g_free (iface->gtype_init);
-       
+
+        g_free (iface->class_struct);  
        g_free (iface->parent);
 
        for (l = iface->interfaces; l; l = l->next)
@@ -431,7 +432,7 @@ g_ir_node_get_size (GIrNode *node)
        GIrNodeInterface *iface = (GIrNodeInterface *)node;
 
        n = g_list_length (iface->interfaces);
-       size = 32 + 2 * (n + (n % 2));
+       size = sizeof(ObjectBlob) + 2 * (n + (n % 2));
 
        for (l = iface->members; l; l = l->next)
          size += g_ir_node_get_size ((GIrNode *)l->data);
@@ -647,9 +648,11 @@ g_ir_node_get_full_size_internal (GIrNode *parent,
        GIrNodeInterface *iface = (GIrNodeInterface *)node;
 
        n = g_list_length (iface->interfaces);
-       size = 32;
+       size = sizeof(ObjectBlob);
        if (iface->parent)
          size += ALIGN_VALUE (strlen (iface->parent) + 1, 4);
+        if (iface->class_struct)
+          size += ALIGN_VALUE (strlen (iface->class_struct) + 1, 4);   
        size += ALIGN_VALUE (strlen (node->name) + 1, 4);
        size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
        if (iface->gtype_init)
@@ -1792,6 +1795,7 @@ g_ir_node_build_typelib (GIrNode    *node,
        
        blob->blob_type = BLOB_TYPE_STRUCT;
        blob->deprecated = struct_->deprecated;
+       blob->is_class_struct = struct_->is_gclass_struct;
        blob->reserved = 0;
        blob->name = write_string (node->name, strings, data, offset2);
        blob->alignment = struct_->alignment;
@@ -2001,6 +2005,10 @@ g_ir_node_build_typelib (GIrNode    *node,
          blob->parent = find_entry (module, modules, object->parent);
        else
          blob->parent = 0;
+       if (object->class_struct)
+         blob->class_struct = find_entry (module, modules, object->class_struct);
+       else
+         blob->class_struct = 0;
 
        blob->n_interfaces = 0;
        blob->n_fields = 0;
@@ -2010,7 +2018,7 @@ g_ir_node_build_typelib (GIrNode    *node,
        blob->n_vfuncs = 0;
        blob->n_constants = 0;
        
-       *offset += 32;
+       *offset += sizeof(ObjectBlob);
        for (l = object->interfaces; l; l = l->next)
          {
            blob->n_interfaces++;
index a1b8f0dc093fe9bf1d3694357b7a67859256d092..fad6799111ca3f009144c279b06dbcd116a64de8 100644 (file)
@@ -228,6 +228,7 @@ struct _GIrNodeInterface
   gchar *gtype_init;
 
   gchar *parent;
+  gchar *class_struct; /* Only applies to classes */
   
   GList *interfaces;
   GList *prerequisites;
@@ -292,6 +293,7 @@ struct _GIrNodeStruct
 
   gboolean deprecated;
   gboolean disguised;
+  gboolean is_gclass_struct;
 
   gchar *gtype_name;
   gchar *gtype_init;
index 3e1f9dfe512b20a04aea199abafd5782bcc02a5f..eb3c11d3e33b5cac6a16cce3bc77385aacf1313a 100644 (file)
@@ -1530,6 +1530,7 @@ start_class (GMarkupParseContext *context,
     {
       const gchar *name;
       const gchar *parent;
+      const gchar *class_struct;      
       const gchar *typename;
       const gchar *typeinit;
       const gchar *deprecated;
@@ -1537,6 +1538,7 @@ start_class (GMarkupParseContext *context,
       
       name = find_attribute ("name", attribute_names, attribute_values);
       parent = find_attribute ("parent", attribute_names, attribute_values);
+      class_struct = find_attribute ("glib:class-struct", attribute_names, attribute_values);      
       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
@@ -1557,6 +1559,7 @@ start_class (GMarkupParseContext *context,
          iface->gtype_name = g_strdup (typename);
          iface->gtype_init = g_strdup (typeinit);
          iface->parent = g_strdup (parent);
+         iface->class_struct = g_strdup (class_struct);
          if (deprecated)
            iface->deprecated = TRUE;
          else
@@ -2122,6 +2125,7 @@ start_struct (GMarkupParseContext *context,
       const gchar *disguised;
       const gchar *gtype_name;
       const gchar *gtype_init;
+      const gchar *gclass_struct;
       GIrNodeStruct *struct_;
       
       name = find_attribute ("name", attribute_names, attribute_values);
@@ -2129,6 +2133,7 @@ start_struct (GMarkupParseContext *context,
       disguised = find_attribute ("disguised", attribute_names, attribute_values);
       gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
       gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
+      gclass_struct = find_attribute ("glib:is-class-struct-for", attribute_names, attribute_values);      
 
       if (name == NULL && ctx->node_stack == NULL)
        {
@@ -2156,6 +2161,8 @@ start_struct (GMarkupParseContext *context,
 
       if (disguised && strcmp (disguised, "1") == 0)
        struct_->disguised = TRUE;
+      
+      struct_->is_gclass_struct = gclass_struct != NULL;
 
       struct_->gtype_name = g_strdup (gtype_name);
       struct_->gtype_init = g_strdup (gtype_init);
index d7b09f214bf15d3472d691096d4288e086658d80..e3b1214ed6819a31e3501758c204af1a730f180a 100644 (file)
@@ -181,7 +181,7 @@ g_typelib_check_sanity (void)
   CHECK_SIZE (PropertyBlob, 12);
   CHECK_SIZE (SignalBlob, 12);
   CHECK_SIZE (VFuncBlob, 16);
-  CHECK_SIZE (ObjectBlob, 32);
+  CHECK_SIZE (ObjectBlob, 36);
   CHECK_SIZE (InterfaceBlob, 28);
   CHECK_SIZE (ConstantBlob, 20);
   CHECK_SIZE (AnnotationBlob, 12);
@@ -313,6 +313,15 @@ validate_header (ValidateContext  *ctx,
                   "Typelib size mismatch");
       return FALSE; 
     }
+  
+  /* This is a sanity check for a specific typelib; it
+   * prevents us from loading an incompatible typelib.  It's OK to change
+   * these hardcoded constants to sizeof() as you see fit.
+   * 
+   * We want to keep the hardcoded checks in g_typelib_check_sanity to
+   * protect against inadvertent or buggy changes to the typelib format
+   * itself.
+   */
 
   if (header->entry_blob_size != 12 ||
       header->function_blob_size != 20 ||
@@ -329,7 +338,7 @@ validate_header (ValidateContext  *ctx,
       header->signature_blob_size != 8 ||
       header->enum_blob_size != 20 ||
       header->struct_blob_size != 24 ||
-      header->object_blob_size != 32 ||
+      header->object_blob_size != sizeof(ObjectBlob) ||
       header->interface_blob_size != 28 ||
       header->union_blob_size != 32)
     {
@@ -1435,7 +1444,9 @@ validate_object_blob (ValidateContext *ctx,
     {
       DirEntry *entry;
 
-      entry = g_typelib_get_dir_entry (typelib, blob->parent);
+      entry = get_dir_entry_checked (typelib, blob->parent, error);
+      if (!entry)
+        return FALSE;
       if (entry->blob_type != BLOB_TYPE_OBJECT &&
          (entry->local || entry->blob_type != 0))
        {
@@ -1447,6 +1458,23 @@ validate_object_blob (ValidateContext *ctx,
        }
     }
   
+  if (blob->class_struct != 0)
+    {
+      DirEntry *entry;
+
+      entry = get_dir_entry_checked (typelib, blob->class_struct, error);
+      if (!entry)
+        return FALSE;
+      if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
+        {
+          g_set_error (error,
+                       G_TYPELIB_ERROR,
+                       G_TYPELIB_ERROR_INVALID_BLOB,
+                       "Class struct invalid type or not local");
+          return FALSE; 
+        }
+    }  
+  
   if (typelib->len < offset + sizeof (ObjectBlob) + 
             (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
             blob->n_fields * sizeof (FieldBlob) +
@@ -1481,7 +1509,9 @@ validate_object_blob (ValidateContext *ctx,
          return FALSE; 
        }
       
-      entry = g_typelib_get_dir_entry (typelib, iface);
+      entry = get_dir_entry_checked (typelib, iface, error);
+      if (!entry)
+        return FALSE;
 
       if (entry->blob_type != BLOB_TYPE_INTERFACE &&
          (entry->local || entry->blob_type != 0))
index a68d008000dcf7d3f0687861dbae1ecd830c7922..ee7442f3752a83a9a459dcc6098dd0d7fd8187bc 100644 (file)
@@ -306,8 +306,9 @@ typedef struct
 
   guint16   deprecated   : 1;
   guint16   unregistered : 1;
-  guint16   alignment    : 6;
-  guint16   reserved     : 8;
+  guint16   is_class_struct : 1;
+  guint16   alignment    : 6;  
+  guint16   reserved     : 7;
 
   guint32   name;
 
@@ -438,6 +439,8 @@ typedef struct
   guint32   gtype_init;
 
   guint16   parent;
+  guint16   class_struct;
+  guint16   reserved2;
 
   guint16   n_interfaces;
   guint16   n_fields;
index 8343009b5e85033f32abfc0fdb2ea266faec7027..14cd1a603eb2cc86cdfb6f5fcb8aa4692ca65627 100644 (file)
@@ -365,6 +365,9 @@ class Record(Node):
         self.doc = None
         self.constructors = []
         self.methods = []
+        # If true, this record defines the FooClass C structure
+        # for some Foo GObject
+        self.is_gobject_struct_for = False
 
 # BW compat, remove
 Struct = Record
@@ -404,6 +407,7 @@ class Class(Node):
         Node.__init__(self, name)
         self.ctype = name
         self.parent = parent
+        self.class_struct = None
         self.is_abstract = is_abstract
         self.methods = []
         self.static_methods = []
index cd19e9890ba1ab56002352b65010e3c957b5834f..657063e641d008f98a11ac91030f898cfe225c46 100644 (file)
@@ -298,6 +298,9 @@ and/or use gtk-doc annotations. ''')
             attrs.append(('glib:type-name', node.type_name))
             if node.get_type:
                 attrs.append(('glib:get-type', node.get_type))
+        if isinstance(node, GLibObject):
+            if node.class_struct:
+                attrs.append(('glib:class-struct', node.class_struct.name))
         with self.tagcontext(tag_name, attrs):
             if isinstance(node, GLibObject):
                 for iface in node.interfaces:
@@ -365,14 +368,17 @@ and/or use gtk-doc annotations. ''')
         return [('glib:type-name', boxed.type_name),
                 ('glib:get-type', boxed.get_type)]
 
-    def _write_record(self, record):
-        attrs = []
+    def _write_record(self, record, extra_attrs=[]):
+        attrs = list(extra_attrs)
         if record.name is not None:
             attrs.append(('name', record.name))
         if record.symbol is not None: # the record might be anonymous
             attrs.append(('c:type', record.symbol))
         if record.disguised:
             attrs.append(('disguised', '1'))
+        if record.is_gobject_struct_for:
+            attrs.append(('glib:is-class-struct-for',
+                          record.is_gobject_struct_for))
         if record.doc:
             attrs.append(('doc', record.doc))
         self._append_version(record, attrs)
index 6b6a2d38cbd29dcfa8f21cf78b24bb39fbbe1d50..f05ce65e5babe8b17317683a21a54dc0d100d9d2 100644 (file)
@@ -545,9 +545,15 @@ class GLibTransformer(object):
         if name == maybe_class.name:
             return
 
-        if self._arg_is_failed(maybe_class):
-            print "WARNING: deleting no-type %r" % (maybe_class.name, )
-            del self._names.names[maybe_class.name]
+        class_struct = maybe_class
+        if self._arg_is_failed(class_struct):
+            print "WARNING: deleting no-type %r" % (class_struct.name, )
+            del self._names.names[class_struct.name]
+            return
+
+        pair_class = self._get_attribute(name)
+        if (not pair_class or
+            not isinstance(pair_class, (GLibObject, GLibInterface))):
             return
 
         # Object class fields are assumed to be read-only
@@ -555,20 +561,13 @@ class GLibTransformer(object):
         for field in maybe_class.fields:
             if isinstance(field, Field):
                 field.writable = False
-
-        name = self._resolve_type_name(name)
-        resolved = self._transformer.remove_prefix(name)
-        pair_class = self._get_attribute(resolved)
-        if pair_class and isinstance(pair_class, GLibInterface):
+        if isinstance(pair_class, GLibInterface):
             for field in maybe_class.fields[1:]:
                 pair_class.fields.append(field)
             return
-        name = self._transformer.remove_prefix(maybe_class.name)
-        pair_class = self._get_attribute(name)
-        if pair_class and isinstance(pair_class,
-                                     (GLibObject, GLibInterface)):
-
-            del self._names.names[maybe_class.name]
+        elif isinstance(pair_class, GLibObject):
+            pair_class.class_struct = class_struct
+            class_struct.is_gobject_struct_for = name
 
     # Introspection
 
index 2ba6b91de85dd19235dcdb10d43ac7bea49fccb9..209f06227d6b096710c264be507a1bf8b01f2828 100644 (file)
@@ -13,12 +13,15 @@ and/or use gtk-doc annotations.  -->
            c:type="BarBaz"
            parent="GObject.Object"
            glib:type-name="BarBaz"
-           glib:get-type="bar_baz_get_type">
+           glib:get-type="bar_baz_get_type"
+           glib:class-struct="BazClass">
       <field name="parent_instance">
         <type name="GObject.Object" c:type="GObject"/>
       </field>
     </class>
-    <record name="BazClass" c:type="BarBazClass">
+    <record name="BazClass"
+            c:type="BarBazClass"
+            glib:is-class-struct-for="Baz">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
index 3de9dad188c7a176156180a964646b49cf6ccdeb..4a99be5de340dee0e6c339bfc174696daee1f8b8 100644 (file)
@@ -6,12 +6,12 @@
   <include name="GObject" version="2.0"/>
   <include name="GLib" version="2.0"/>
   <namespace name="BarApp" version="1.0" shared-library="">
-    <class name="Baz" parent="GObject.Object" glib:type-name="BarBaz" glib:get-type="bar_baz_get_type">
+    <class name="Baz" parent="GObject.Object" glib:class-struct="BazClass" glib:type-name="BarBaz" glib:get-type="bar_baz_get_type">
       <field name="parent_instance">
         <type name="GObject.Object"/>
       </field>
     </class>
-    <record name="BazClass">
+    <record name="BazClass" glib:is-class-struct="1">
       <field name="parent_class">
         <type name="GObject.ObjectClass"/>
       </field>
index ba4d991acc3b2ae2a330109facf8d159cc449ab5..11ee31e1e811d5ce12dd5ebfa24d36898609876a 100644 (file)
@@ -43,7 +43,8 @@ and/or use gtk-doc annotations.  -->
            doc="This is an object used to test annotations."
            parent="GObject.Object"
            glib:type-name="AnnotationObject"
-           glib:get-type="annotation_object_get_type">
+           glib:get-type="annotation_object_get_type"
+           glib:class-struct="ObjectClass">
       <method name="method" c:identifier="annotation_object_method">
         <return-value transfer-ownership="none">
           <type name="int" c:type="gint"/>
@@ -452,7 +453,9 @@ known by GObject as it&apos;s only marked as G_TYPE_POINTER">
         </parameters>
       </glib:signal>
     </class>
-    <record name="ObjectClass" c:type="AnnotationObjectClass">
+    <record name="ObjectClass"
+            c:type="AnnotationObjectClass"
+            glib:is-class-struct-for="Object">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
index 756c81c5dc38ad5c76ecaad763a9bae2fdadd617..bb85894e3329e936d271a5223cfce0d2ffcf82ca 100644 (file)
@@ -31,7 +31,7 @@
         </parameter>
       </parameters>
     </callback>
-    <class name="Object" parent="GObject.Object" glib:type-name="AnnotationObject" glib:get-type="annotation_object_get_type">
+    <class name="Object" parent="GObject.Object" glib:class-struct="ObjectClass" glib:type-name="AnnotationObject" glib:get-type="annotation_object_get_type">
       <field name="parent_instance">
         <type name="GObject.Object"/>
       </field>
           </type>
         </return-value>
       </method>
+      <method name="with_voidp" c:identifier="annotation_object_with_voidp">
+        <return-value transfer-ownership="none">
+          <type name="none"/>
+        </return-value>
+        <parameters>
+          <parameter name="data" transfer-ownership="none">
+            <type name="any"/>
+          </parameter>
+        </parameters>
+      </method>
       <method name="get_objects" c:identifier="annotation_object_get_objects">
         <return-value transfer-ownership="container">
           <type name="GLib.SList">
         </parameters>
       </glib:signal>
     </class>
-    <record name="ObjectClass">
+    <record name="ObjectClass" glib:is-class-struct="1">
       <field name="parent_class">
         <type name="GObject.ObjectClass"/>
       </field>
index 79eba8b140b0ddfe8c0e0ca7de98640e3118d567..738296ffd13cb90e7e10a88872e58c88a1493011 100644 (file)
@@ -15,7 +15,8 @@ and/or use gtk-doc annotations.  -->
            parent="GObject.Object"
            abstract="1"
            glib:type-name="TestDrawable"
-           glib:get-type="test_drawable_get_type">
+           glib:get-type="test_drawable_get_type"
+           glib:class-struct="TestDrawableClass">
       <method name="do_foo" c:identifier="test_drawable_do_foo">
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -68,13 +69,15 @@ and/or use gtk-doc annotations.  -->
         <type name="GObject.Object" c:type="GObject"/>
       </field>
     </class>
-    <record name="TestDrawableClass" c:type="TestDrawableClass">
+    <record name="TestDrawableClass"
+            c:type="TestDrawableClass"
+            glib:is-class-struct-for="TestDrawable">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
     </record>
     <record name="TestPixmapObjectClass" c:type="_TestPixmapObjectClass">
-      <field name="parent_class">
+      <field name="parent_class" writable="1">
         <type name="TestDrawableClass" c:type="TestDrawableClass"/>
       </field>
     </record>
index 0a31714099f32e87638a16afc120932d653ca4d8..612022b70da688a4d38d08a0dc951c9a2b30479d 100644 (file)
@@ -7,7 +7,7 @@
   <include name="GObject" version="2.0"/>
   <include name="GLib" version="2.0"/>
   <namespace name="drawable" version="1.0" shared-library="drawable">
-    <class name="TestDrawable" parent="GObject.Object" abstract="1" glib:type-name="TestDrawable" glib:get-type="test_drawable_get_type">
+    <class name="TestDrawable" parent="GObject.Object" glib:class-struct="TestDrawableClass" abstract="1" glib:type-name="TestDrawable" glib:get-type="test_drawable_get_type">
       <field name="parent_instance">
         <type name="GObject.Object"/>
       </field>
         </parameters>
       </method>
     </class>
-    <record name="TestDrawableClass">
+    <record name="TestDrawableClass" glib:is-class-struct="1">
       <field name="parent_class">
         <type name="GObject.ObjectClass"/>
       </field>
     </record>
     <record name="TestPixmapObjectClass">
-      <field name="parent_class">
+      <field name="parent_class" writable="1">
         <type name="TestDrawableClass"/>
       </field>
     </record>
index 2d69099b231ffa967d915c0679452be4f74d9363..7bc200955b2296eead5d1f63edfeadfebfefd343 100644 (file)
@@ -83,7 +83,8 @@ and/or use gtk-doc annotations.  -->
            c:type="FooObject"
            parent="GObject.Object"
            glib:type-name="FooObject"
-           glib:get-type="foo_object_get_type">
+           glib:get-type="foo_object_get_type"
+           glib:class-struct="ObjectClass">
       <implements name="Interface"/>
       <constructor name="new" c:identifier="foo_object_new">
         <return-value transfer-ownership="full">
@@ -200,7 +201,9 @@ and/or use gtk-doc annotations.  -->
         </parameters>
       </glib:signal>
     </class>
-    <record name="ObjectClass" c:type="FooObjectClass">
+    <record name="ObjectClass"
+            c:type="FooObjectClass"
+            glib:is-class-struct-for="Object">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
@@ -223,7 +226,8 @@ and/or use gtk-doc annotations.  -->
            parent="Object"
            abstract="1"
            glib:type-name="FooSubobject"
-           glib:get-type="foo_subobject_get_type">
+           glib:get-type="foo_subobject_get_type"
+           glib:class-struct="SubobjectClass">
       <implements name="Interface"/>
       <constructor name="new" c:identifier="foo_subobject_new">
         <return-value transfer-ownership="full">
@@ -234,7 +238,9 @@ and/or use gtk-doc annotations.  -->
         <type name="Object" c:type="FooObject"/>
       </field>
     </class>
-    <record name="SubobjectClass" c:type="FooSubobjectClass">
+    <record name="SubobjectClass"
+            c:type="FooSubobjectClass"
+            glib:is-class-struct-for="Subobject">
       <field name="parent_class">
         <type name="ObjectClass" c:type="FooObjectClass"/>
       </field>
@@ -243,7 +249,8 @@ and/or use gtk-doc annotations.  -->
            c:type="FooBuffer"
            parent="GObject.Object"
            glib:type-name="FooBuffer"
-           glib:get-type="foo_buffer_get_type">
+           glib:get-type="foo_buffer_get_type"
+           glib:class-struct="BufferClass">
       <implements name="Interface"/>
       <method name="some_method" c:identifier="foo_buffer_some_method">
         <return-value transfer-ownership="none">
@@ -251,7 +258,9 @@ and/or use gtk-doc annotations.  -->
         </return-value>
       </method>
     </class>
-    <record name="BufferClass" c:type="FooBufferClass">
+    <record name="BufferClass"
+            c:type="FooBufferClass"
+            glib:is-class-struct-for="Buffer">
     </record>
     <function name="init" c:identifier="foo_init">
       <return-value transfer-ownership="none">
index 80e6fc5070a8dbfb1156fcecaeb163162bb8f67e..3f57f3c0ceca9f617dedcf409b0d68ee76699e3c 100644 (file)
@@ -26,7 +26,7 @@
         <type name="GObject.TypeInterface"/>
       </field>
     </record>
-    <class name="Object" parent="GObject.Object" glib:type-name="FooObject" glib:get-type="foo_object_get_type">
+    <class name="Object" parent="GObject.Object" glib:class-struct="ObjectClass" glib:type-name="FooObject" glib:get-type="foo_object_get_type">
       <implements name="Interface"/>
       <field name="parent_instance">
         <type name="GObject.Object"/>
         </parameters>
       </glib:signal>
     </class>
-    <record name="ObjectClass">
+    <record name="ObjectClass" glib:is-class-struct="1">
       <field name="parent_class">
         <type name="GObject.ObjectClass"/>
       </field>
     </record>
-    <class name="Subobject" parent="Object" abstract="1" glib:type-name="FooSubobject" glib:get-type="foo_subobject_get_type">
+    <class name="Subobject" parent="Object" glib:class-struct="SubobjectClass" abstract="1" glib:type-name="FooSubobject" glib:get-type="foo_subobject_get_type">
       <implements name="Interface"/>
       <field name="parent_instance">
         <type name="Object"/>
         </return-value>
       </constructor>
     </class>
-    <record name="SubobjectClass">
+    <record name="SubobjectClass" glib:is-class-struct="1">
       <field name="parent_class">
         <type name="ObjectClass"/>
       </field>
     </record>
-    <class name="Buffer" parent="GObject.Object" glib:type-name="FooBuffer" glib:get-type="foo_buffer_get_type">
+    <class name="Buffer" parent="GObject.Object" glib:class-struct="BufferClass" glib:type-name="FooBuffer" glib:get-type="foo_buffer_get_type">
       <implements name="Interface"/>
       <method name="some_method" c:identifier="foo_buffer_some_method">
         <return-value transfer-ownership="none">
         </return-value>
       </method>
     </class>
-    <record name="BufferClass"/>
+    <record name="BufferClass"  glib:is-class-struct="1"/>
     <function name="init" c:identifier="foo_init">
       <return-value transfer-ownership="none">
         <type name="int"/>
index bb5a5e466d62510b21b58af5d272f1e8b2bfcfa6..c04d984d8938bb26b7bbd128534e7c21ad87a9b6 100644 (file)
@@ -14,7 +14,8 @@ and/or use gtk-doc annotations.  -->
            c:type="UtilityObject"
            parent="GObject.Object"
            glib:type-name="UtilityObject"
-           glib:get-type="utility_object_get_type">
+           glib:get-type="utility_object_get_type"
+           glib:class-struct="ObjectClass">
       <method name="watch_dir" c:identifier="utility_object_watch_dir">
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -41,7 +42,9 @@ and/or use gtk-doc annotations.  -->
         <type name="GObject.Object" c:type="GObject"/>
       </field>
     </class>
-    <record name="ObjectClass" c:type="UtilityObjectClass">
+    <record name="ObjectClass"
+            c:type="UtilityObjectClass"
+            glib:is-class-struct-for="Object">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
index 08ba692c63606e964dae4392eab23f6c9eb022d0..e55fc80ecf5830cead80e7060e58a3cc6559062f 100644 (file)
@@ -6,7 +6,7 @@
   <include name="GObject" version="2.0"/>
   <include name="GLib" version="2.0"/>
   <namespace name="utility" version="1.0" shared-library="utility">
-    <class name="Object" parent="GObject.Object" glib:type-name="UtilityObject" glib:get-type="utility_object_get_type">
+    <class name="Object" parent="GObject.Object" glib:class-struct="ObjectClass" glib:type-name="UtilityObject" glib:get-type="utility_object_get_type">
       <field name="parent_instance">
         <type name="GObject.Object"/>
       </field>
@@ -30,7 +30,7 @@
         </parameters>
       </method>
     </class>
-    <record name="ObjectClass">
+    <record name="ObjectClass" glib:is-class-struct="1">
       <field name="parent_class">
         <type name="GObject.ObjectClass"/>
       </field>
index dcc36faf9af4e7ef1542b6f0c004e38b7741a095..8b4185fcec050f8aba28278758e711c5c950c410 100644 (file)
@@ -566,6 +566,7 @@ write_struct_info (const gchar  *namespace,
   const gchar *type_name;
   const gchar *type_init;
   gboolean deprecated;
+  gboolean is_class_struct;
   gint i;
   int n_elts;
 
@@ -591,6 +592,10 @@ write_struct_info (const gchar  *namespace,
          
   if (deprecated)
     xml_printf (file, " deprecated=\"1\"");
+  
+  is_class_struct = g_struct_info_is_class_struct (info);
+  if (is_class_struct)
+    xml_printf (file, " glib:is-class-struct=\"1\"");
        
   n_elts = g_struct_info_get_n_fields (info) + g_struct_info_get_n_methods (info);
   if (n_elts > 0)
@@ -904,6 +909,7 @@ write_object_info (const gchar  *namespace,
   gboolean deprecated;
   gboolean is_abstract;
   GIObjectInfo *pnode;
+  GIStructInfo *class_struct;
   gint i;
 
   name = g_base_info_get_name ((GIBaseInfo *)info);
@@ -921,6 +927,13 @@ write_object_info (const gchar  *namespace,
       write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
       g_base_info_unref ((GIBaseInfo *)pnode);
     }
+  
+  class_struct = g_object_info_get_class_struct (info);
+  if (class_struct)
+    {
+      write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:class-struct", file);
+      g_base_info_unref ((GIBaseInfo*)class_struct);
+    }
 
   if (is_abstract)
     xml_printf (file, " abstract=\"1\"");