[gobject-introspection] Implement callbacks as part of struct fields. Fixes #557383



commit f8693bda3775f6339f38a17c037ac7bc4a4cc3f7
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date:   Mon Nov 9 19:17:23 2009 +0100

    Implement callbacks as part of struct fields. Fixes #557383
    
    gir: embed <callback> inside <field>
    typelib: if a field contains a callback, store it just after the FieldBlob
    girepository API: no additions

 gir/Everything-1.0-expected.gir     |   28 ++++----
 girepository/ginfo.c                |   67 +++++++++++++++---
 girepository/girepository.h         |    6 +-
 girepository/girnode.c              |   34 +++++++--
 girepository/girnode.h              |    1 +
 girepository/giroffsets.c           |    9 ++-
 girepository/girparser.c            |   20 +++++-
 girepository/gtypelib.c             |   35 ++++++---
 girepository/gtypelib.h             |    4 +-
 giscanner/girwriter.py              |    5 +-
 tests/scanner/foo-1.0-expected.gir  |  134 +++++++++++++++++++----------------
 tests/scanner/foo-1.0-expected.tgir |   72 +++++++++++++++++++
 tools/generate.c                    |   18 ++++-
 13 files changed, 321 insertions(+), 112 deletions(-)
---
diff --git a/gir/Everything-1.0-expected.gir b/gir/Everything-1.0-expected.gir
index dabfb81..6944fc6 100644
--- a/gir/Everything-1.0-expected.gir
+++ b/gir/Everything-1.0-expected.gir
@@ -215,19 +215,21 @@ case.">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
-      <callback name="matrix" c:type="matrix">
-        <return-value transfer-ownership="none">
-          <type name="int" c:type="int"/>
-        </return-value>
-        <parameters>
-          <parameter name="obj" transfer-ownership="none">
-            <type name="TestObj" c:type="TestObj*"/>
-          </parameter>
-          <parameter name="somestr" transfer-ownership="none">
-            <type name="utf8" c:type="char*"/>
-          </parameter>
-        </parameters>
-      </callback>
+      <field name="matrix">
+        <callback name="matrix" c:type="matrix">
+          <return-value transfer-ownership="none">
+            <type name="int" c:type="int"/>
+          </return-value>
+          <parameters>
+            <parameter name="obj" transfer-ownership="none">
+              <type name="TestObj" c:type="TestObj*"/>
+            </parameter>
+            <parameter name="somestr" transfer-ownership="none">
+              <type name="utf8" c:type="char*"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
       <field name="test_signal">
         <type name="uint" c:type="guint"/>
       </field>
diff --git a/girepository/ginfo.c b/girepository/ginfo.c
index eef3cd6..1f14cb6 100644
--- a/girepository/ginfo.c
+++ b/girepository/ginfo.c
@@ -134,6 +134,7 @@ struct _GIArgInfo
 struct _GITypeInfo
 {
   GIBaseInfo base;
+  gboolean   is_embedded;
 };
 
 struct _GIUnionInfo
@@ -154,7 +155,10 @@ g_info_new_full (GIInfoType     type,
 
   g_return_val_if_fail (container != NULL || repository != NULL, NULL);
 
-  info = g_new0 (GIBaseInfo, 1);
+  if (type == GI_INFO_TYPE_TYPE)
+    info = (GIBaseInfo *)g_new0 (GITypeInfo, 1);
+  else
+    info = g_new0 (GIBaseInfo, 1);
 
   info->ref_count = 1;
   info->type = type;
@@ -643,9 +647,13 @@ g_type_info_new (GIBaseInfo    *container,
 		 guint32        offset)
 {
   SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
+  GITypeInfo *type_info;
 
-  return (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, typelib, 
+  type_info = (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, typelib, 
 				    (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
+  type_info->is_embedded = FALSE;
+
+  return type_info;
 }
 
 /**
@@ -876,7 +884,9 @@ g_type_info_get_tag (GITypeInfo *info)
   GIBaseInfo *base = (GIBaseInfo *)info;
   SimpleTypeBlob *type = (SimpleTypeBlob *)&base->typelib->data[base->offset];
 
-  if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
+  if (info->is_embedded)
+    return GI_TYPE_TAG_INTERFACE;
+  else if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
     return type->flags.tag;
   else
     {
@@ -920,7 +930,11 @@ g_type_info_get_interface (GITypeInfo *info)
 {
   GIBaseInfo *base = (GIBaseInfo *)info;
   SimpleTypeBlob *type = (SimpleTypeBlob *)&base->typelib->data[base->offset];
-  
+
+  if (info->is_embedded)
+    return (GIBaseInfo *) g_info_new (type->offset, base, base->typelib,
+				      base->offset);
+
   if (!(type->flags.reserved == 0 && type->flags.reserved2 == 0))
     {
       InterfaceTypeBlob *blob = (InterfaceTypeBlob *)&base->typelib->data[base->offset];
@@ -1100,8 +1114,21 @@ GITypeInfo *
 g_field_info_get_type (GIFieldInfo *info)
 {
   GIBaseInfo *base = (GIBaseInfo *)info;
-  
-  return g_type_info_new (base, base->typelib, base->offset + G_STRUCT_OFFSET (FieldBlob, type));
+  Header *header = (Header *)base->typelib->data;
+  FieldBlob *blob = (FieldBlob *)&base->typelib->data[base->offset];
+  GITypeInfo *type_info;
+
+  if (blob->has_embedded_type)
+    {
+      type_info = (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE,
+                                             (GIBaseInfo*)info, base->typelib,
+                                             base->offset + header->field_blob_size);
+      type_info->is_embedded = TRUE;
+    }
+  else
+    return g_type_info_new (base, base->typelib, base->offset + G_STRUCT_OFFSET (FieldBlob, type));
+
+  return type_info;
 }
 
 /* GIRegisteredTypeInfo functions */
@@ -1161,16 +1188,35 @@ g_struct_info_get_n_fields (GIStructInfo *info)
   return blob->n_fields;
 }
 
+static gint32
+g_struct_get_field_offset (GIStructInfo *info,
+			   gint         n)
+{
+  GIBaseInfo *base = (GIBaseInfo *)info;
+  Header *header = (Header *)base->typelib->data;
+  guint32 offset = base->offset + header->struct_blob_size;
+  gint i;
+  FieldBlob *field_blob;
+
+  for (i = 0; i < n; i++)
+    {
+      field_blob = (FieldBlob *)&base->typelib->data[offset];
+      offset += header->field_blob_size;
+      if (field_blob->has_embedded_type)
+        offset += header->callback_blob_size;
+    }
+
+  return offset;
+}
+
 GIFieldInfo *
 g_struct_info_get_field (GIStructInfo *info,
 			 gint         n)
 {
   GIBaseInfo *base = (GIBaseInfo *)info;
-  Header *header = (Header *)base->typelib->data;  
  
   return (GIFieldInfo *) g_info_new (GI_INFO_TYPE_FIELD, base, base->typelib, 
-				     base->offset + header->struct_blob_size + 
-				     n * header->field_blob_size);
+				     g_struct_get_field_offset (info, n));
 }
 
 gint
@@ -1191,8 +1237,7 @@ g_struct_info_get_method (GIStructInfo *info,
   Header *header = (Header *)base->typelib->data;  
   gint offset;
 
-  offset = base->offset + header->struct_blob_size 
-    + blob->n_fields * header->field_blob_size 
+  offset = g_struct_get_field_offset (info, blob->n_fields)
     + n * header->function_blob_size;
   return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, base, 
 					base->typelib, offset);
diff --git a/girepository/girepository.h b/girepository/girepository.h
index 559be1e..c881c8b 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -162,17 +162,17 @@ typedef enum
   GI_INFO_TYPE_CALLBACK,
   GI_INFO_TYPE_STRUCT,
   GI_INFO_TYPE_BOXED,
-  GI_INFO_TYPE_ENUM,
+  GI_INFO_TYPE_ENUM,         /*  5 */
   GI_INFO_TYPE_FLAGS,
   GI_INFO_TYPE_OBJECT,
   GI_INFO_TYPE_INTERFACE,
   GI_INFO_TYPE_CONSTANT,
-  GI_INFO_TYPE_ERROR_DOMAIN,
+  GI_INFO_TYPE_ERROR_DOMAIN, /* 10 */
   GI_INFO_TYPE_UNION,
   GI_INFO_TYPE_VALUE,
   GI_INFO_TYPE_SIGNAL,
   GI_INFO_TYPE_VFUNC,
-  GI_INFO_TYPE_PROPERTY,
+  GI_INFO_TYPE_PROPERTY,     /* 15 */
   GI_INFO_TYPE_FIELD,
   GI_INFO_TYPE_ARG,
   GI_INFO_TYPE_TYPE,
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 22e821e..9f62345 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -279,6 +279,7 @@ g_ir_node_free (GIrNode *node)
 	
 	g_free (node->name);
 	g_ir_node_free ((GIrNode *)field->type);
+	g_ir_node_free ((GIrNode *)field->callback);
       }
       break;
 
@@ -508,7 +509,13 @@ g_ir_node_get_size (GIrNode *node)
       break;
 
     case G_IR_NODE_FIELD:
-      size = sizeof (FieldBlob);
+      {
+	GIrNodeField *field = (GIrNodeField *)node;
+
+        size = sizeof (FieldBlob);
+        if (field->callback)
+          size += g_ir_node_get_size ((GIrNode *)field->callback);
+      }
       break;
 
     case G_IR_NODE_CONSTANT:
@@ -797,7 +804,10 @@ g_ir_node_get_full_size_internal (GIrNode *parent,
 
 	size = sizeof (FieldBlob);
 	size += ALIGN_VALUE (strlen (node->name) + 1, 4);
-	size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->type);	
+	if (field->callback)
+          size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->callback);
+	else
+          size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->type);
       }
       break;
 
@@ -1587,8 +1597,6 @@ g_ir_node_build_typelib (GIrNode         *node,
 	FieldBlob *blob;
 
 	blob = (FieldBlob *)&data[*offset];
-	/* We handle the size member specially below, so subtract it */
-	*offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob);
 
 	blob->name = write_string (node->name, strings, data, offset2);
 	blob->readable = field->readable;
@@ -1600,8 +1608,22 @@ g_ir_node_build_typelib (GIrNode         *node,
 	else
 	  blob->struct_offset = 0xFFFF; /* mark as unknown */
 
-        g_ir_node_build_typelib ((GIrNode *)field->type, 
-				 node, build, offset, offset2);
+        if (field->callback)
+          {
+            blob->has_embedded_type = TRUE;
+            blob->type.offset = GI_INFO_TYPE_CALLBACK;
+	    *offset += sizeof (FieldBlob);
+            g_ir_node_build_typelib ((GIrNode *)field->callback,
+			             node, build, offset, offset2);
+          }
+        else
+          {
+            blob->has_embedded_type = FALSE;
+            /* We handle the size member specially below, so subtract it */
+	    *offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob);
+            g_ir_node_build_typelib ((GIrNode *)field->type,
+				     node, build, offset, offset2);
+          }
       }
       break;
 
diff --git a/girepository/girnode.h b/girepository/girnode.h
index 238593a..c1b2369 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -230,6 +230,7 @@ struct _GIrNodeField
   gboolean writable;
   gint bits;
   gint offset;
+  GIrNodeFunction *callback;
   
   GIrNodeType *type;
 };
diff --git a/girepository/giroffsets.c b/girepository/giroffsets.c
index d834746..8354bc5 100644
--- a/girepository/giroffsets.c
+++ b/girepository/giroffsets.c
@@ -303,7 +303,14 @@ get_field_size_alignment (GIrNodeField *field,
   
   who = g_strdup_printf ("field %s.%s.%s", module->name, parent_node->name, ((GIrNode *)field)->name);
 
-  success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
+  if (field->callback)
+    {
+      *size = ffi_type_pointer.size;
+      *alignment = ffi_type_pointer.alignment;
+      success = TRUE;
+    }
+  else
+    success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
   g_free (who);
 
   return success;
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 9387d25..1bbe59f 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -101,6 +101,7 @@ struct _ParseContext
   GList *type_stack;
   GList *type_parameters;
   int type_depth;
+  gboolean in_embedded_type;
 };
 #define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
 
@@ -719,6 +720,10 @@ start_function (GMarkupParseContext *context,
 	       strcmp (element_name, "method") == 0 ||
 	       strcmp (element_name, "callback") == 0);
       break;
+    case STATE_STRUCT_FIELD:
+      ctx->in_embedded_type = TRUE;
+      found = (found || strcmp (element_name, "callback") == 0);
+      break;
     default:
       break;
     }
@@ -782,6 +787,13 @@ start_function (GMarkupParseContext *context,
       ctx->current_module->entries = 
 	g_list_append (ctx->current_module->entries, function);	      
     }
+  else if (ctx->current_typed)
+    {
+      GIrNodeField *field;
+
+      field = (GIrNodeField *)ctx->current_typed;
+      field->callback = function;
+    }
   else
     switch (CURRENT_NODE (ctx)->type)
       {
@@ -2902,7 +2914,13 @@ end_element_handler (GMarkupParseContext *context,
 	  }
 	else 
 	  {
-	    if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
+            g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
+            if (ctx->in_embedded_type)
+              {
+                ctx->in_embedded_type = FALSE;
+                state_switch (ctx, STATE_STRUCT_FIELD);
+              }
+	    else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
 	      state_switch (ctx, STATE_INTERFACE);
 	    else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT) 
 	      state_switch (ctx, STATE_CLASS);
diff --git a/girepository/gtypelib.c b/girepository/gtypelib.c
index e7572ea..30f7961 100644
--- a/girepository/gtypelib.c
+++ b/girepository/gtypelib.c
@@ -1016,10 +1016,12 @@ validate_value_blob (GTypelib     *typelib,
 }
 
 static gboolean
-validate_field_blob (GTypelib     *typelib,
+validate_field_blob (ValidateContext *ctx,
 		     guint32        offset,
 		     GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
+  Header *header = (Header *)typelib->data;
   FieldBlob *blob;
 
   if (typelib->len < offset + sizeof (FieldBlob))
@@ -1035,10 +1037,15 @@ validate_field_blob (GTypelib     *typelib,
   
   if (!validate_name (typelib, "field", typelib->data, blob->name, error))
     return FALSE; 
-  
-  if (!validate_type_blob (typelib,
-			   offset + G_STRUCT_OFFSET (FieldBlob, type), 
-			   0, FALSE, error))
+
+  if (blob->has_embedded_type)
+    {
+      if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
+        return FALSE;
+    }
+  else if (!validate_type_blob (typelib,
+			        offset + G_STRUCT_OFFSET (FieldBlob, type), 
+			        0, FALSE, error))
     return FALSE;
 
   return TRUE;
@@ -1209,6 +1216,7 @@ validate_struct_blob (ValidateContext *ctx,
   GTypelib *typelib = ctx->typelib;
   StructBlob *blob;
   gint i;
+  guint32 field_offset;
 
   if (typelib->len < offset + sizeof (StructBlob))
     {
@@ -1266,20 +1274,25 @@ validate_struct_blob (ValidateContext *ctx,
       return FALSE;
     }
 
+  field_offset = offset + sizeof (StructBlob);
   for (i = 0; i < blob->n_fields; i++)
     {
-      if (!validate_field_blob (typelib, 
-				offset + sizeof (StructBlob) + 
-				i * sizeof (FieldBlob), 
+      FieldBlob *blob = (FieldBlob*) &typelib->data[field_offset];
+
+      if (!validate_field_blob (ctx,
+				field_offset,
 				error))
 	return FALSE;
+
+      field_offset += sizeof (FieldBlob);
+      if (blob->has_embedded_type)
+        field_offset += sizeof (CallbackBlob);
     }
 
   for (i = 0; i < blob->n_methods; i++)
     {
       if (!validate_function_blob (ctx, 
-				   offset + sizeof (StructBlob) + 
-				   blob->n_fields * sizeof (FieldBlob) + 
+				   field_offset + 
 				   i * sizeof (FunctionBlob), 
 				   blob_type,
 				   error))
@@ -1532,7 +1545,7 @@ validate_object_blob (ValidateContext *ctx,
   
   for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
     {
-      if (!validate_field_blob (typelib, offset2, error))
+      if (!validate_field_blob (ctx, offset2, error))
 	return FALSE;
     }
 
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index 015682e..26486af 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -622,6 +622,7 @@ typedef struct {
  * @name: The name of the field.
  * @readable:
  * @writable: How the field may be accessed.
+ * @has_embedded_type: An anonymous type follows the FieldBlob.
  * @bits: If this field is part of a bitfield, the number of bits which it
  * uses, otherwise 0.
  * @struct_offset:
@@ -634,7 +635,8 @@ typedef struct {
 
   guint8         readable :1; 
   guint8         writable :1;
-  guint8         reserved :6;
+  guint8         has_embedded_type :1;
+  guint8         reserved :5;
   guint8         bits;
 
   guint16        struct_offset;
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 7697a2d..47df929 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -464,7 +464,10 @@ and/or use gtk-doc annotations. ''')
             return
 
         if isinstance(field, Callback):
-            self._write_callback(field)
+            attrs = [('name', field.name)]
+            with self.tagcontext('field', attrs):
+                self._write_attributes(field)
+                self._write_callback(field)
         elif isinstance(field, Struct):
             self._write_record(field)
         elif isinstance(field, Union):
diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir
index 24e9fbb..85c2322 100644
--- a/tests/scanner/foo-1.0-expected.gir
+++ b/tests/scanner/foo-1.0-expected.gir
@@ -267,19 +267,21 @@ and/or use gtk-doc annotations.  -->
       <field name="parent_iface">
         <type name="GObject.TypeInterface" c:type="GTypeInterface"/>
       </field>
-      <callback name="do_foo" c:type="do_foo">
-        <return-value transfer-ownership="none">
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="self" transfer-ownership="none">
-            <type name="Interface" c:type="FooInterface*"/>
-          </parameter>
-          <parameter name="x" transfer-ownership="none">
-            <type name="int" c:type="int"/>
-          </parameter>
-        </parameters>
-      </callback>
+      <field name="do_foo">
+        <callback name="do_foo" c:type="do_foo">
+          <return-value transfer-ownership="none">
+            <type name="none" c:type="void"/>
+          </return-value>
+          <parameters>
+            <parameter name="self" transfer-ownership="none">
+              <type name="Interface" c:type="FooInterface*"/>
+            </parameter>
+            <parameter name="x" transfer-ownership="none">
+              <type name="int" c:type="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
     </record>
     <class name="Object"
            c:type="FooObject"
@@ -465,35 +467,39 @@ uses a C sugar return type.">
       <field name="parent_class">
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
-      <callback name="virtual_method" c:type="virtual_method">
-        <return-value transfer-ownership="none">
-          <type name="boolean" c:type="gboolean"/>
-        </return-value>
-        <parameters>
-          <parameter name="object" transfer-ownership="none">
-            <type name="Object" c:type="FooObject*"/>
-          </parameter>
-          <parameter name="first_param" transfer-ownership="none">
-            <type name="int" c:type="int"/>
-          </parameter>
-        </parameters>
-      </callback>
-      <callback name="read_fn" c:type="read_fn">
-        <return-value transfer-ownership="none">
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="object" transfer-ownership="none">
-            <type name="Object" c:type="FooObject*"/>
-          </parameter>
-          <parameter name="offset" transfer-ownership="none">
-            <type name="int" c:type="int"/>
-          </parameter>
-          <parameter name="length" transfer-ownership="none">
-            <type name="int" c:type="int"/>
-          </parameter>
-        </parameters>
-      </callback>
+      <field name="virtual_method">
+        <callback name="virtual_method" c:type="virtual_method">
+          <return-value transfer-ownership="none">
+            <type name="boolean" c:type="gboolean"/>
+          </return-value>
+          <parameters>
+            <parameter name="object" transfer-ownership="none">
+              <type name="Object" c:type="FooObject*"/>
+            </parameter>
+            <parameter name="first_param" transfer-ownership="none">
+              <type name="int" c:type="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
+      <field name="read_fn">
+        <callback name="read_fn" c:type="read_fn">
+          <return-value transfer-ownership="none">
+            <type name="none" c:type="void"/>
+          </return-value>
+          <parameters>
+            <parameter name="object" transfer-ownership="none">
+              <type name="Object" c:type="FooObject*"/>
+            </parameter>
+            <parameter name="offset" transfer-ownership="none">
+              <type name="int" c:type="int"/>
+            </parameter>
+            <parameter name="length" transfer-ownership="none">
+              <type name="int" c:type="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
       <field name="_reserved">
         <array zero-terminated="0" c:type="GCallback" fixed-size="4">
           <type name="GObject.Callback"/>
@@ -602,26 +608,30 @@ uses a C sugar return type.">
       <field name="parent_iface">
         <type name="GObject.TypeInterface" c:type="GTypeInterface"/>
       </field>
-      <callback name="destroy_event" c:type="destroy_event">
-        <return-value transfer-ownership="none">
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="self" transfer-ownership="none">
-            <type name="SubInterface" c:type="FooSubInterface*"/>
-          </parameter>
-        </parameters>
-      </callback>
-      <callback name="do_bar" c:type="do_bar">
-        <return-value transfer-ownership="none">
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="self" transfer-ownership="none">
-            <type name="SubInterface" c:type="FooSubInterface*"/>
-          </parameter>
-        </parameters>
-      </callback>
+      <field name="destroy_event">
+        <callback name="destroy_event" c:type="destroy_event">
+          <return-value transfer-ownership="none">
+            <type name="none" c:type="void"/>
+          </return-value>
+          <parameters>
+            <parameter name="self" transfer-ownership="none">
+              <type name="SubInterface" c:type="FooSubInterface*"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
+      <field name="do_bar">
+        <callback name="do_bar" c:type="do_bar">
+          <return-value transfer-ownership="none">
+            <type name="none" c:type="void"/>
+          </return-value>
+          <parameters>
+            <parameter name="self" transfer-ownership="none">
+              <type name="SubInterface" c:type="FooSubInterface*"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
     </record>
     <class name="Subobject"
            c:type="FooSubobject"
diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir
index 2de826b..8504bc4 100644
--- a/tests/scanner/foo-1.0-expected.tgir
+++ b/tests/scanner/foo-1.0-expected.tgir
@@ -190,6 +190,21 @@
       <field name="parent_iface">
         <type name="GObject.TypeInterface"/>
       </field>
+      <field name="do_foo">
+        <callback name="do_foo">
+          <return-value transfer-ownership="none">
+            <type name="none"/>
+          </return-value>
+          <parameters>
+            <parameter name="self" transfer-ownership="none">
+              <type name="Interface"/>
+            </parameter>
+            <parameter name="x" transfer-ownership="none">
+              <type name="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
     </record>
     <class name="Object" parent="GObject.Object" glib:type-struct="ObjectClass" glib:type-name="FooObject" glib:get-type="foo_object_get_type">
       <implements name="Interface"/>
@@ -351,6 +366,39 @@
       <field name="parent_class">
         <type name="GObject.ObjectClass"/>
       </field>
+      <field name="virtual_method">
+        <callback name="virtual_method">
+          <return-value transfer-ownership="none">
+            <type name="boolean"/>
+          </return-value>
+          <parameters>
+            <parameter name="object" transfer-ownership="none">
+              <type name="Object"/>
+            </parameter>
+            <parameter name="first_param" transfer-ownership="none">
+              <type name="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
+      <field name="read_fn">
+        <callback name="read_fn">
+          <return-value transfer-ownership="none">
+            <type name="none"/>
+          </return-value>
+          <parameters>
+            <parameter name="object" transfer-ownership="none">
+              <type name="Object"/>
+            </parameter>
+            <parameter name="offset" transfer-ownership="none">
+              <type name="int"/>
+            </parameter>
+            <parameter name="length" transfer-ownership="none">
+              <type name="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
       <field name="_reserved">
         <array fixed-size="4">
           <type name="GObject.Callback"/>
@@ -448,6 +496,30 @@
       <field name="parent_iface">
         <type name="GObject.TypeInterface"/>
       </field>
+      <field name="destroy_event">
+        <callback name="destroy_event">
+          <return-value transfer-ownership="none">
+            <type name="none"/>
+          </return-value>
+          <parameters>
+            <parameter name="self" transfer-ownership="none">
+              <type name="SubInterface"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
+      <field name="do_bar">
+        <callback name="do_bar">
+          <return-value transfer-ownership="none">
+            <type name="none"/>
+          </return-value>
+          <parameters>
+            <parameter name="self" transfer-ownership="none">
+              <type name="SubInterface"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </field>
     </record>
     <class name="Subobject" parent="Object" glib:type-struct="SubobjectClass" abstract="1" glib:type-name="FooSubobject" glib:get-type="foo_subobject_get_type">
       <implements name="Interface"/>
diff --git a/tools/generate.c b/tools/generate.c
index a71f365..fcff5b6 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -340,6 +340,11 @@ write_constant_value (const gchar *namespace,
 		      Xml *file);
 
 static void
+write_callback_info (const gchar    *namespace,
+		     GICallbackInfo *info,
+		     Xml            *file);
+
+static void
 write_field_info (const gchar *namespace,
 		  GIFieldInfo *info,
 		  GIConstantInfo *branch,
@@ -350,6 +355,7 @@ write_field_info (const gchar *namespace,
   gint size;
   gint offset;
   GITypeInfo *type;
+  GIBaseInfo *interface;
   GArgument value; 
 
   name = g_base_info_get_name ((GIBaseInfo *)info);
@@ -389,8 +395,16 @@ write_field_info (const gchar *namespace,
       if (offset >= 0)
         xml_printf (file, "offset=\"%d\"", offset);
     }
-  
-  write_type_info (namespace, type, file);
+
+  interface = g_type_info_get_interface (type);
+  if (interface && g_base_info_get_type(interface) == GI_INFO_TYPE_CALLBACK)
+    write_callback_info (namespace, (GICallbackInfo *)interface, file);
+  else
+    write_type_info (namespace, type, file);
+
+  if (interface)
+    g_base_info_unref (interface);
+
   g_base_info_unref ((GIBaseInfo *)type);
 
   xml_end_element (file, "field");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]