summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@sugarlabs.org>2009-11-09 19:17:23 +0100
committerTomeu Vizoso <tomeu@sugarlabs.org>2009-11-11 13:55:00 +0100
commitf8693bda3775f6339f38a17c037ac7bc4a4cc3f7 (patch)
tree89456982ed5b6e8e5850a7c05f55a50f3be0c5fa
parent3715b02198c9efc34d70f489d4e55a39456d8f99 (diff)
downloadgobject-introspection-f8693bda3775f6339f38a17c037ac7bc4a4cc3f7.tar.gz
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
-rw-r--r--gir/Everything-1.0-expected.gir28
-rw-r--r--girepository/ginfo.c67
-rw-r--r--girepository/girepository.h6
-rw-r--r--girepository/girnode.c34
-rw-r--r--girepository/girnode.h1
-rw-r--r--girepository/giroffsets.c9
-rw-r--r--girepository/girparser.c20
-rw-r--r--girepository/gtypelib.c35
-rw-r--r--girepository/gtypelib.h4
-rw-r--r--giscanner/girwriter.py5
-rw-r--r--tests/scanner/foo-1.0-expected.gir134
-rw-r--r--tests/scanner/foo-1.0-expected.tgir72
-rw-r--r--tools/generate.c18
13 files changed, 321 insertions, 112 deletions
diff --git a/gir/Everything-1.0-expected.gir b/gir/Everything-1.0-expected.gir
index dabfb815..6944fc69 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 eef3cd6e..1f14cb6f 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 559be1ee..c881c8bb 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 22e821e0..9f623453 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 238593ae..c1b2369c 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 d8347464..8354bc51 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 9387d252..1bbe59fd 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 e7572ea5..30f79617 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 015682e2..26486afc 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 7697a2df..47df929c 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 24e9fbb3..85c2322a 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 2de826b5..8504bc49 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 a71f3654..fcff5b62 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");