summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Rottmann <a.rottmann@gmx.at>2009-01-03 13:44:42 +0000
committerJürg Billeter <juergbi@src.gnome.org>2009-01-03 13:44:42 +0000
commitbc88ef7bcda59b15988d27517a4f4f7e0672e33b (patch)
tree7e3af8b1d130ca9e4b5e78fb7314340d02b11eca
parent00b0ae6bca603adc2c424c9a9384c60c4e4b1ccb (diff)
downloadgobject-introspection-bc88ef7bcda59b15988d27517a4f4f7e0672e33b.tar.gz
Bug 556489 – callback annotations
2008-01-03 Andreas Rottmann <a.rottmann@gmx.at> Bug 556489 – callback annotations * giscanner/transformer.py * tools/generate.c (write_callable_info): Write out the new scope, closure and destroy attributes. * giscanner/transformer.py (Transformer._type_is_callback): New method, checking if a given type is a callback. (Transformer._augment_callback_params): New method; adds information (closure, destroy) to callback parameters. (Transformer._handle_closure, Transformer._handle_destroy): New methods, auxiliary to _augment_callback_params. (Transformer._create_function): Call _augment_callback_params(). (Transformer._create_parameter): Handle scope option. (Transformer._create_typedef_callback): New method, creates a callback, and registers it in the typedef namespace (Transformer._create_typedef): Use _create_typedef_callback() instead of the plain _create_callback(). * giscanner/ast.py (Parameter): Added callback-related fields. * giscanner/girwriter.py: Write out new Parameter fields. * girepository/girnode.h (GIrNodeParam): Added fields scope, closure and destroy. * girepository/gtypelib.h (ArgBlob): Ditto. * girepository/girparser.c (start_parameter): Handle new fields. * girepository/girmodule.c (g_ir_module_build_typelib): Adjust arg_blob_size, bump major version due to this change. * girepository/girnode.c (g_ir_node_get_full_size_internal) (g_ir_node_build_typelib) * girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size adjustments. (g_ir_node_build_typelib): Fill in new ArgBlob flags from param. * girepository/girepository.h (GIScope): New enumeration, listing the different possible scopes for callbacks. * girepository/ginfo.c (g_arg_info_get_scope) (g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for callback-related argument indices (callback scope, closure for a callback, destroy notification for a callback). * tests/scanner/: Added testcases for new features. svn path=/trunk/; revision=998
-rw-r--r--ChangeLog49
-rw-r--r--docs/typelib-format.txt32
-rw-r--r--girepository/ginfo.c29
-rw-r--r--girepository/girepository.h11
-rw-r--r--girepository/girmodule.c4
-rw-r--r--girepository/girnode.c9
-rw-r--r--girepository/girnode.h4
-rw-r--r--girepository/girparser.c22
-rw-r--r--girepository/gtypelib.c6
-rw-r--r--girepository/gtypelib.h6
-rw-r--r--giscanner/ast.py5
-rw-r--r--giscanner/girwriter.py6
-rw-r--r--giscanner/transformer.py56
-rw-r--r--tests/scanner/annotation-1.0-expected.gir32
-rw-r--r--tests/scanner/annotation-1.0-expected.tgir29
-rw-r--r--tests/scanner/annotation.c16
-rw-r--r--tests/scanner/annotation.h7
-rw-r--r--tests/scanner/utility-1.0-expected.gir51
-rw-r--r--tests/scanner/utility-1.0-expected.tgir48
-rw-r--r--tests/scanner/utility.c15
-rw-r--r--tests/scanner/utility.h11
-rw-r--r--tools/generate.c24
22 files changed, 456 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 8bf8a3bd..bae3d7a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+2008-01-03 Andreas Rottmann <a.rottmann@gmx.at>
+
+ Bug 556489 – callback annotations
+
+ * giscanner/transformer.py
+
+ * tools/generate.c (write_callable_info): Write out the new scope,
+ closure and destroy attributes.
+
+ * giscanner/transformer.py (Transformer._type_is_callback): New
+ method, checking if a given type is a callback.
+ (Transformer._augment_callback_params): New method; adds
+ information (closure, destroy) to callback parameters.
+ (Transformer._handle_closure, Transformer._handle_destroy): New methods,
+ auxiliary to _augment_callback_params.
+ (Transformer._create_function): Call _augment_callback_params().
+ (Transformer._create_parameter): Handle scope option.
+
+ (Transformer._create_typedef_callback): New method, creates a
+ callback, and registers it in the typedef namespace
+ (Transformer._create_typedef): Use _create_typedef_callback()
+ instead of the plain _create_callback().
+
+ * giscanner/ast.py (Parameter): Added callback-related fields.
+ * giscanner/girwriter.py: Write out new Parameter fields.
+
+ * girepository/girnode.h (GIrNodeParam): Added fields scope,
+ closure and destroy.
+ * girepository/gtypelib.h (ArgBlob): Ditto.
+ * girepository/girparser.c (start_parameter): Handle new fields.
+
+ * girepository/girmodule.c (g_ir_module_build_typelib): Adjust
+ arg_blob_size, bump major version due to this change.
+ * girepository/girnode.c (g_ir_node_get_full_size_internal)
+ (g_ir_node_build_typelib)
+ * girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size
+ adjustments.
+ (g_ir_node_build_typelib): Fill in new ArgBlob flags from param.
+
+ * girepository/girepository.h (GIScope): New enumeration, listing
+ the different possible scopes for callbacks.
+
+ * girepository/ginfo.c (g_arg_info_get_scope)
+ (g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for
+ callback-related argument indices (callback scope, closure for a
+ callback, destroy notification for a callback).
+
+ * tests/scanner/: Added testcases for new features.
+
2009-01-03 Jürg Billeter <j@bitron.ch>
* giscanner/ast.py:
diff --git a/docs/typelib-format.txt b/docs/typelib-format.txt
index 895c1f0d..a47a9f78 100644
--- a/docs/typelib-format.txt
+++ b/docs/typelib-format.txt
@@ -391,7 +391,11 @@ struct ArgBlob
guint transfer_ownership : 1;
guint transfer_container_ownership : 1;
guint is_return_value : 1;
- guint reserved :24:
+ guint scope : 3;
+ guint reserved :21:
+
+ gint8 closure;
+ gint8 destroy;
SimpleTypeBlob arg_type;
}
@@ -437,7 +441,31 @@ is_return_value:
at most one per function call. If an out parameter is marked as
return value, the actual return value of the function should be
either void or a boolean indicating the success of the call.
-
+
+scope:
+ If the parameter is of a callback type, this denotes the scope
+ of the user_data and the callback function pointer itself
+ (for languages that emit code at run-time).
+
+ 0 invalid -- the argument is not of callback type
+ 1 call -- the callback and associated user_data is
+ only used during the call to this function
+ 2 object -- the callback and associated user_data is
+ used until the object containing this method is destroyed
+ 3 async -- the callback and associated user_data is
+ only used until the callback is invoked, and the callback
+ is invoked always exactly once.
+ 4 notified -- the callback and and associated user_data is
+ used until the caller is notfied via the destroy_notify
+
+closure:
+ Index of the closure (user_data) parameter associated with the callback,
+ or -1.
+
+destroy:
+ Index of the destroy notfication callback parameter associated with
+ the callback, or -1.
+
arg_type:
Describes the type of the parameter. See details below.
diff --git a/girepository/ginfo.c b/girepository/ginfo.c
index 5df1e3f8..8324c05b 100644
--- a/girepository/ginfo.c
+++ b/girepository/ginfo.c
@@ -741,12 +741,39 @@ g_arg_info_get_ownership_transfer (GIArgInfo *info)
return GI_TRANSFER_NOTHING;
}
+GIScopeType
+g_arg_info_get_scope (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->typelib->data[base->offset];
+
+ return blob->scope;
+}
+
+gint
+g_arg_info_get_closure (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->typelib->data[base->offset];
+
+ return blob->closure;
+}
+
+gint
+g_arg_info_get_destroy (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->typelib->data[base->offset];
+
+ return blob->destroy;
+}
+
GITypeInfo *
g_arg_info_get_type (GIArgInfo *info)
{
GIBaseInfo *base = (GIBaseInfo *)info;
- return g_type_info_new (base, base->typelib, base->offset + 8);
+ return g_type_info_new (base, base->typelib, base->offset + 12);
}
/* GITypeInfo functions */
diff --git a/girepository/girepository.h b/girepository/girepository.h
index abeb8570..38697c69 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -269,12 +269,23 @@ typedef enum {
GI_DIRECTION_INOUT
} GIDirection;
+typedef enum {
+ GI_SCOPE_TYPE_INVALID,
+ GI_SCOPE_TYPE_CALL,
+ GI_SCOPE_TYPE_OBJECT,
+ GI_SCOPE_TYPE_ASYNC,
+ GI_SCOPE_TYPE_NOTIFIED
+} GIScopeType;
+
GIDirection g_arg_info_get_direction (GIArgInfo *info);
gboolean g_arg_info_is_dipper (GIArgInfo *info);
gboolean g_arg_info_is_return_value (GIArgInfo *info);
gboolean g_arg_info_is_optional (GIArgInfo *info);
gboolean g_arg_info_may_be_null (GIArgInfo *info);
GITransfer g_arg_info_get_ownership_transfer (GIArgInfo *info);
+GIScopeType g_arg_info_get_scope (GIArgInfo *info);
+gint g_arg_info_get_closure (GIArgInfo *info);
+gint g_arg_info_get_destroy (GIArgInfo *info);
GITypeInfo * g_arg_info_get_type (GIArgInfo *info);
diff --git a/girepository/girmodule.c b/girepository/girmodule.c
index be41a1ed..85103bff 100644
--- a/girepository/girmodule.c
+++ b/girepository/girmodule.c
@@ -190,7 +190,7 @@ g_ir_module_build_typelib (GIrModule *module,
/* fill in header */
header = (Header *)data;
memcpy (header, G_IR_MAGIC, 16);
- header->major_version = 1;
+ header->major_version = 2;
header->minor_version = 0;
header->reserved = 0;
header->n_entries = n_entries;
@@ -213,7 +213,7 @@ g_ir_module_build_typelib (GIrModule *module,
header->callback_blob_size = 12;
header->signal_blob_size = 12;
header->vfunc_blob_size = 16;
- header->arg_blob_size = 12;
+ header->arg_blob_size = 16;
header->property_blob_size = 12;
header->field_blob_size = 12;
header->value_blob_size = 12;
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 61e4f0b6..c4045ef7 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -582,7 +582,7 @@ g_ir_node_get_full_size_internal (GIrNode *parent,
{
GIrNodeParam *param = (GIrNodeParam *)node;
- size = 12;
+ size = 16;
if (node->name)
size += ALIGN_VALUE (strlen (node->name) + 1, 4);
size += g_ir_node_get_full_size_internal (node, (GIrNode *)param->type);
@@ -1764,7 +1764,7 @@ g_ir_node_build_typelib (GIrNode *node,
ArgBlob *blob = (ArgBlob *)&data[*offset];
GIrNodeParam *param = (GIrNodeParam *)node;
- *offset += 8;
+ *offset += 12;
blob->name = write_string (node->name, strings, data, offset2);
blob->in = param->in;
@@ -1775,8 +1775,11 @@ g_ir_node_build_typelib (GIrNode *node,
blob->transfer_ownership = param->transfer;
blob->transfer_container_ownership = param->shallow_transfer;
blob->return_value = param->retval;
+ blob->scope = param->scope;
blob->reserved = 0;
-
+ blob->closure = param->closure;
+ blob->destroy = param->destroy;
+
g_ir_node_build_typelib ((GIrNode *)param->type, module, modules,
strings, types, data, offset, offset2);
}
diff --git a/girepository/girnode.h b/girepository/girnode.h
index 674594d8..a1b8f0dc 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -143,6 +143,10 @@ struct _GIrNodeParam
gboolean allow_none;
gboolean transfer;
gboolean shallow_transfer;
+ GIScopeType scope;
+
+ gint8 closure;
+ gint8 destroy;
GIrNodeType *type;
};
diff --git a/girepository/girparser.c b/girepository/girparser.c
index e6d59b4c..1072ecc5 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -837,6 +837,9 @@ start_parameter (GMarkupParseContext *context,
const gchar *optional;
const gchar *allow_none;
const gchar *transfer;
+ const gchar *scope;
+ const gchar *closure;
+ const gchar *destroy;
GIrNodeParam *param;
if (!(strcmp (element_name, "parameter") == 0 &&
@@ -850,7 +853,10 @@ start_parameter (GMarkupParseContext *context,
optional = find_attribute ("optional", attribute_names, attribute_values);
allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
-
+ scope = find_attribute ("scope", attribute_names, attribute_values);
+ closure = find_attribute ("closure", attribute_names, attribute_values);
+ destroy = find_attribute ("destroy", attribute_names, attribute_values);
+
if (name == NULL)
name = "unknown";
@@ -899,6 +905,20 @@ start_parameter (GMarkupParseContext *context,
parse_param_transfer (param, transfer);
+ if (scope && strcmp (scope, "call") == 0)
+ param->scope = GI_SCOPE_TYPE_CALL;
+ else if (scope && strcmp (scope, "object") == 0)
+ param->scope = GI_SCOPE_TYPE_OBJECT;
+ else if (scope && strcmp (scope, "async") == 0)
+ param->scope = GI_SCOPE_TYPE_ASYNC;
+ else if (scope && strcmp (scope, "notified") == 0)
+ param->scope = GI_SCOPE_TYPE_NOTIFIED;
+ else
+ param->scope = GI_SCOPE_TYPE_INVALID;
+
+ param->closure = closure ? atoi (closure) : -1;
+ param->destroy = destroy ? atoi (destroy) : -1;
+
((GIrNode *)param)->name = g_strdup (name);
switch (ctx->current_node->type)
diff --git a/girepository/gtypelib.c b/girepository/gtypelib.c
index 51cbafcd..d7b09f21 100644
--- a/girepository/gtypelib.c
+++ b/girepository/gtypelib.c
@@ -164,7 +164,7 @@ g_typelib_check_sanity (void)
CHECK_SIZE (Header, 108);
CHECK_SIZE (DirEntry, 12);
CHECK_SIZE (SimpleTypeBlob, 4);
- CHECK_SIZE (ArgBlob, 12);
+ CHECK_SIZE (ArgBlob, 16);
CHECK_SIZE (SignatureBlob, 8);
CHECK_SIZE (CommonBlob, 8);
CHECK_SIZE (FunctionBlob, 20);
@@ -286,7 +286,7 @@ validate_header (ValidateContext *ctx,
}
- if (header->major_version != 1 || header->minor_version != 0)
+ if (header->major_version != 2 || header->minor_version != 0)
{
g_set_error (error,
G_TYPELIB_ERROR,
@@ -319,7 +319,7 @@ validate_header (ValidateContext *ctx,
header->callback_blob_size != 12 ||
header->signal_blob_size != 12 ||
header->vfunc_blob_size != 16 ||
- header->arg_blob_size != 12 ||
+ header->arg_blob_size != 16 ||
header->property_blob_size != 12 ||
header->field_blob_size != 12 ||
header->value_blob_size != 12 ||
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index 343f9e1b..a68d0080 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -132,7 +132,11 @@ typedef struct
guint transfer_ownership : 1;
guint transfer_container_ownership : 1;
guint return_value : 1;
- guint reserved :24;
+ guint scope : 3;
+ guint reserved :21;
+
+ gint8 closure;
+ gint8 destroy;
SimpleTypeBlob arg_type;
} ArgBlob;
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 7df1bf69..6bd858b2 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -289,7 +289,7 @@ class TypeContainer(Node):
class Parameter(TypeContainer):
def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
- transfer=None, allow_none=False):
+ transfer=None, allow_none=False, scope=None):
TypeContainer.__init__(self, name, typenode, transfer)
if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
PARAM_DIRECTION_INOUT]:
@@ -298,6 +298,9 @@ class Parameter(TypeContainer):
self.direction = PARAM_DIRECTION_IN
self.allow_none = not not allow_none
+ self.scope = scope
+ self.closure_index = -1
+ self.destroy_index = -1
def __repr__(self):
return 'Parameter(%r, %r)' % (self.name, self.type)
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 4468e25b..f82a73e5 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -162,6 +162,12 @@ class GIRWriter(XMLWriter):
parameter.transfer))
if parameter.allow_none:
attrs.append(('allow-none', '1'))
+ if parameter.scope:
+ attrs.append(('scope', parameter.scope))
+ if parameter.closure_index >= 0:
+ attrs.append(('closure', '%d' % parameter.closure_index))
+ if parameter.destroy_index >= 0:
+ attrs.append(('destroy', '%d' % parameter.destroy_index))
with self.tagcontext('parameter', attrs):
self._write_type(parameter.type)
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index e7c7214a..0ed7ca00 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -269,6 +269,52 @@ class Transformer(object):
if isinstance(return_.type, Array):
self._pair_array(params, return_)
+ def _type_is_callback(self, type):
+ if (isinstance(type, Callback) or
+ isinstance(self._typedefs_ns.get(type.name), Callback)):
+ return True
+ return False
+
+ def _handle_closure(self, param, closure_idx, closure_param):
+ if (closure_param.type.name == 'any' and
+ closure_param.name == 'user_data'):
+ param.closure_name = closure_param.name
+ param.closure_index = closure_idx
+ return True
+ return False
+
+ def _handle_destroy(self, param, destroy_idx, destroy_param):
+ if ((self._namespace.name == 'GLib' and
+ destroy_param.type.name == 'DestroyNotify') or
+ destroy_param.type.name == 'GLib.DestroyNotify'):
+ param.destroy_name = destroy_param.name
+ param.destroy_index = destroy_idx
+ return True
+ return False
+
+ def _augment_callback_params(self, params):
+ for i, param in enumerate(params):
+ if self._type_is_callback(param.type):
+ # j is the index where we look for closure/destroy to
+ # group with the callback param
+ j = i + 1
+ if j == len(params):
+ continue # no more args -> nothing to group look
+ # at the param directly following for either a closure
+ # or a destroy; only one of these will fire
+ had_closure = self._handle_closure(param, j, params[j])
+ had_destroy = self._handle_destroy(param, j, params[j])
+ j += 1
+ # are we out of params, or did we find neither?
+ if j == len(params) or (not had_closure and not had_destroy):
+ continue
+ # we found either a closure or a destroy; check the
+ # parameter following for the other
+ if not had_closure:
+ self._handle_closure(param, j, params[j])
+ if not had_destroy:
+ self._handle_destroy(param, j, params[j])
+
# We take the annotations from the parser as strings; here we
# want to split them into components, so:
# (transfer full) -> {'transfer' : [ 'full' ]}
@@ -286,6 +332,7 @@ class Transformer(object):
symbol.base_type, directives))
return_ = self._create_return(symbol.base_type.base_type,
directives.get('return', {}))
+ self._augment_callback_params(parameters)
self._pair_annotations(parameters, return_)
name = self._strip_namespace_func(symbol.ident)
func = Function(name, return_, parameters, symbol.ident)
@@ -357,7 +404,7 @@ class Transformer(object):
ctype = symbol.base_type.type
if (ctype == CTYPE_POINTER and
symbol.base_type.base_type.type == CTYPE_FUNCTION):
- node = self._create_callback(symbol)
+ node = self._create_typedef_callback(symbol)
elif (ctype == CTYPE_POINTER and
symbol.base_type.base_type.type == CTYPE_STRUCT):
node = self._create_typedef_struct(symbol, disguised=True)
@@ -586,6 +633,8 @@ class Transformer(object):
pass
elif option in ('transfer', 'transfer-inferred'):
pass
+ elif option == 'scope':
+ param.scope = data[0]
else:
print 'Unhandled parameter annotation option: %r' % (
option, )
@@ -642,6 +691,11 @@ class Transformer(object):
self._create_union(symbol)
return union
+ def _create_typedef_callback(self, symbol):
+ callback = self._create_callback(symbol)
+ self._typedefs_ns[callback.name] = callback
+ return callback
+
def _create_struct(self, symbol):
directives = symbol.directives()
struct = self._typedefs_ns.get(symbol.ident, None)
diff --git a/tests/scanner/annotation-1.0-expected.gir b/tests/scanner/annotation-1.0-expected.gir
index 88dcdc6a..155b9c4a 100644
--- a/tests/scanner/annotation-1.0-expected.gir
+++ b/tests/scanner/annotation-1.0-expected.gir
@@ -245,6 +245,22 @@
</parameter>
</parameters>
</method>
+ <method name="foreach" c:identifier="annotation_object_foreach">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="func"
+ transfer-ownership="none"
+ scope="call"
+ closure="2">
+ <type name="ForeachFunc" c:type="AnnotationForeachFunc"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any" c:type="gpointer"/>
+ </parameter>
+ </parameters>
+ </method>
<method name="do_not_use"
c:identifier="annotation_object_do_not_use"
deprecated="Use annotation_object_create_object() instead."
@@ -262,6 +278,22 @@
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
</record>
+ <callback name="ForeachFunc" c:type="AnnotationForeachFunc">
+ <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="AnnotationObject*"/>
+ </parameter>
+ <parameter name="item" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any" c:type="gpointer"/>
+ </parameter>
+ </parameters>
+ </callback>
<function name="init" c:identifier="annotation_init">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
diff --git a/tests/scanner/annotation-1.0-expected.tgir b/tests/scanner/annotation-1.0-expected.tgir
index 4fe10bd6..576d6d74 100644
--- a/tests/scanner/annotation-1.0-expected.tgir
+++ b/tests/scanner/annotation-1.0-expected.tgir
@@ -234,6 +234,19 @@
</parameter>
</parameters>
</method>
+ <method name="foreach" c:identifier="annotation_object_foreach">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="func" transfer-ownership="none" scope="call" closure="2">
+ <type name="ForeachFunc"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any"/>
+ </parameter>
+ </parameters>
+ </method>
<method name="do_not_use" c:identifier="annotation_object_do_not_use" deprecated="1">
<return-value transfer-ownership="full">
<type name="GObject.Object"/>
@@ -245,6 +258,22 @@
<type name="GObject.ObjectClass"/>
</field>
</record>
+ <callback name="ForeachFunc">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="object" transfer-ownership="none">
+ <type name="Object"/>
+ </parameter>
+ <parameter name="item" transfer-ownership="none">
+ <type name="utf8"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any"/>
+ </parameter>
+ </parameters>
+ </callback>
<function name="init" c:identifier="annotation_init">
<return-value transfer-ownership="none">
<type name="none"/>
diff --git a/tests/scanner/annotation.c b/tests/scanner/annotation.c
index cbb69b72..6278b6ce 100644
--- a/tests/scanner/annotation.c
+++ b/tests/scanner/annotation.c
@@ -308,6 +308,22 @@ annotation_object_string_out(AnnotationObject *object,
}
/**
+ * annotation_object_foreach:
+ * @object: a #AnnotationObject
+ * @func: (scope call): Callback to invoke
+ * @user_data: Callback user data
+ *
+ * Test taking a call-scoped callback
+ **/
+void
+annotation_object_foreach (AnnotationObject *object,
+ AnnotationForeachFunc func,
+ gpointer user_data)
+{
+
+}
+
+/**
* annotation_object_allow_none:
* @object: a #GObject
* @somearg: (allow-none):
diff --git a/tests/scanner/annotation.h b/tests/scanner/annotation.h
index 1e83ca23..87946609 100644
--- a/tests/scanner/annotation.h
+++ b/tests/scanner/annotation.h
@@ -22,6 +22,10 @@ typedef GList* (*AnnotationListCallback) (GList *in);
typedef struct _AnnotationObject AnnotationObject;
typedef struct _AnnotationObjectClass AnnotationObjectClass;
+typedef void (*AnnotationForeachFunc) (AnnotationObject *object,
+ const char *item,
+ gpointer user_data);
+
struct _AnnotationObject
{
GObject parent_instance;
@@ -75,6 +79,9 @@ void annotation_object_parse_args (AnnotationObject *object,
char ***argv);
gboolean annotation_object_string_out (AnnotationObject *object,
char **str_out);
+void annotation_object_foreach (AnnotationObject *object,
+ AnnotationForeachFunc func,
+ gpointer user_data);
GObject* annotation_object_do_not_use (AnnotationObject *object);
diff --git a/tests/scanner/utility-1.0-expected.gir b/tests/scanner/utility-1.0-expected.gir
index c01ec4cb..6642d2fc 100644
--- a/tests/scanner/utility-1.0-expected.gir
+++ b/tests/scanner/utility-1.0-expected.gir
@@ -12,6 +12,28 @@
parent="GObject.Object"
glib:type-name="UtilityObject"
glib:get-type="utility_object_get_type">
+ <method name="watch_dir" c:identifier="utility_object_watch_dir">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="path" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ <parameter name="func"
+ transfer-ownership="none"
+ closure="3"
+ destroy="4">
+ <type name="FileFunc" c:type="UtilityFileFunc"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any" c:type="gpointer"/>
+ </parameter>
+ <parameter name="destroy" transfer-ownership="none">
+ <type name="GLib.DestroyNotify" c:type="GDestroyNotify"/>
+ </parameter>
+ </parameters>
+ </method>
<field name="parent_instance">
<type name="GObject.Object" c:type="GObject"/>
</field>
@@ -21,6 +43,19 @@
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
</record>
+ <callback name="FileFunc" c:type="UtilityFileFunc">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="path" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any" c:type="gpointer"/>
+ </parameter>
+ </parameters>
+ </callback>
<enumeration name="EnumType" c:type="UtilityEnumType">
<member name="a" value="0" c:identifier="UTILITY_ENUM_A"/>
<member name="b" value="1" c:identifier="UTILITY_ENUM_B"/>
@@ -58,5 +93,21 @@
<type name="double" c:type="double"/>
</field>
</union>
+ <function name="dir_foreach" c:identifier="utility_dir_foreach">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="path" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ <parameter name="func" transfer-ownership="none" closure="2">
+ <type name="FileFunc" c:type="UtilityFileFunc"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any" c:type="gpointer"/>
+ </parameter>
+ </parameters>
+ </function>
</namespace>
</repository>
diff --git a/tests/scanner/utility-1.0-expected.tgir b/tests/scanner/utility-1.0-expected.tgir
index 236e2d72..26e6d196 100644
--- a/tests/scanner/utility-1.0-expected.tgir
+++ b/tests/scanner/utility-1.0-expected.tgir
@@ -10,12 +10,44 @@
<field name="parent_instance">
<type name="GObject.Object"/>
</field>
+ <method name="watch_dir" c:identifier="utility_object_watch_dir">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="path" transfer-ownership="none">
+ <type name="utf8"/>
+ </parameter>
+ <parameter name="func" transfer-ownership="none" closure="3" destroy="4">
+ <type name="FileFunc"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any"/>
+ </parameter>
+ <parameter name="destroy" transfer-ownership="none">
+ <type name="GLib.DestroyNotify"/>
+ </parameter>
+ </parameters>
+ </method>
</class>
<record name="ObjectClass">
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
</record>
+ <callback name="FileFunc">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="path" transfer-ownership="none">
+ <type name="utf8"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any"/>
+ </parameter>
+ </parameters>
+ </callback>
<enumeration name="EnumType">
<member name="a" value="0"/>
<member name="b" value="1"/>
@@ -53,5 +85,21 @@
<type name="double"/>
</field>
</union>
+ <function name="dir_foreach" c:identifier="utility_dir_foreach">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="path" transfer-ownership="none">
+ <type name="utf8"/>
+ </parameter>
+ <parameter name="func" transfer-ownership="none" closure="2">
+ <type name="FileFunc"/>
+ </parameter>
+ <parameter name="user_data" transfer-ownership="none">
+ <type name="any"/>
+ </parameter>
+ </parameters>
+ </function>
</namespace>
</repository>
diff --git a/tests/scanner/utility.c b/tests/scanner/utility.c
index 45b4bd28..756de178 100644
--- a/tests/scanner/utility.c
+++ b/tests/scanner/utility.c
@@ -14,3 +14,18 @@ utility_object_init (UtilityObject *object)
}
+void
+utility_object_watch_dir (UtilityObject *object,
+ const char *path,
+ UtilityFileFunc func,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+
+}
+
+void
+utility_dir_foreach (const char *path, UtilityFileFunc func, gpointer user_data)
+{
+
+}
diff --git a/tests/scanner/utility.h b/tests/scanner/utility.h
index a592a96d..a744f037 100644
--- a/tests/scanner/utility.h
+++ b/tests/scanner/utility.h
@@ -23,7 +23,14 @@ struct _UtilityObjectClass
/* This one is similar to Pango.Glyph */
typedef guint32 UtilityGlyph;
+typedef void (*UtilityFileFunc)(const char *path, gpointer user_data);
+
GType utility_object_get_type (void) G_GNUC_CONST;
+void utility_object_watch_dir (UtilityObject *object,
+ const char *path,
+ UtilityFileFunc func,
+ gpointer user_data,
+ GDestroyNotify destroy);
typedef enum
{
@@ -53,5 +60,7 @@ typedef union
glong integer;
double real;
} UtilityUnion;
-
+
+void utility_dir_foreach (const char *path, UtilityFileFunc func, gpointer user_data);
+
#endif /* __UTILITY_H__ */
diff --git a/tools/generate.c b/tools/generate.c
index 7c849bcd..dcc36faf 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -455,6 +455,30 @@ write_callable_info (const gchar *namespace,
if (g_arg_info_is_optional (arg))
xml_printf (file, " optional=\"1\"");
+
+ switch (g_arg_info_get_scope (arg))
+ {
+ case GI_SCOPE_TYPE_INVALID:
+ break;
+ case GI_SCOPE_TYPE_CALL:
+ xml_printf (file, " scope=\"call\"");
+ break;
+ case GI_SCOPE_TYPE_OBJECT:
+ xml_printf (file, " scope=\"object\"");
+ break;
+ case GI_SCOPE_TYPE_ASYNC:
+ xml_printf (file, " scope=\"async\"");
+ break;
+ case GI_SCOPE_TYPE_NOTIFIED:
+ xml_printf (file, " scope=\"notified\"");
+ break;
+ }
+
+ if (g_arg_info_get_closure (arg) >= 0)
+ xml_printf (file, " closure=\"%d\"", g_arg_info_get_closure (arg));
+
+ if (g_arg_info_get_destroy (arg) >= 0)
+ xml_printf (file, " destroy=\"%d\"", g_arg_info_get_destroy (arg));
type = g_arg_info_get_type (arg);
write_type_info (namespace, type, file);