Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--girepository/ginfo.c116
-rw-r--r--girepository/girepository.h5
-rw-r--r--girepository/girnode.c37
-rw-r--r--girepository/girnode.h2
-rw-r--r--girepository/girparser.c6
-rw-r--r--girepository/gtypelib.h8
-rw-r--r--giscanner/annotationparser.py57
-rw-r--r--giscanner/ast.py36
-rw-r--r--giscanner/girwriter.py47
-rw-r--r--giscanner/glibtransformer.py73
-rw-r--r--tests/everything/everything.c25
-rw-r--r--tests/everything/everything.h6
-rw-r--r--tests/repository/Makefile.am4
-rw-r--r--tests/repository/gitestrepo.c48
-rw-r--r--tests/scanner/foo-1.0-expected.gir111
-rw-r--r--tests/scanner/foo-1.0-expected.tgir79
-rw-r--r--tests/scanner/foo.c53
-rw-r--r--tests/scanner/foo.h17
-rw-r--r--tools/generate.c9
19 files changed, 655 insertions, 84 deletions
diff --git a/girepository/ginfo.c b/girepository/ginfo.c
index fcc5f09..d522a56 100644
--- a/girepository/ginfo.c
+++ b/girepository/ginfo.c
@@ -1527,6 +1527,63 @@ g_object_info_get_vfunc (GIObjectInfo *info,
base->typelib, offset);
}
+static GIVFuncInfo *
+find_vfunc (GIBaseInfo *base,
+ guint32 offset,
+ gint n_vfuncs,
+ const gchar *name)
+{
+ /* FIXME hash */
+ Header *header = (Header *)base->typelib->data;
+ gint i;
+
+ for (i = 0; i < n_vfuncs; i++)
+ {
+ VFuncBlob *fblob = (VFuncBlob *)&base->typelib->data[offset];
+ const gchar *fname = (const gchar *)&base->typelib->data[fblob->name];
+
+ if (strcmp (name, fname) == 0)
+ return (GIVFuncInfo *) g_info_new (GI_INFO_TYPE_VFUNC, base,
+ base->typelib, offset);
+
+ offset += header->vfunc_blob_size;
+ }
+
+ return NULL;
+}
+
+/**
+ * g_object_info_find_vfunc:
+ * @info: An #GIObjectInfo
+ * @name: The name of a virtual function to find.
+ *
+ * Locate a virtual function slot with name @name. Note that the namespace
+ * for virtuals is distinct from that of methods; there may or may not be
+ * a concrete method associated for a virtual. If there is one, it may
+ * be retrieved using #g_vfunc_info_get_invoker. See the documentation for
+ * that function for more information on invoking virtuals.
+ *
+ * Return value: (transfer full): A #GIVFuncInfo, or %NULL if none with name @name.
+ */
+GIVFuncInfo *
+g_object_info_find_vfunc (GIObjectInfo *info,
+ const gchar *name)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->typelib->data;
+ ObjectBlob *blob = (ObjectBlob *)&base->typelib->data[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + blob->n_signals * header->signal_blob_size;
+
+ return find_vfunc (base, offset, blob->n_vfuncs, name);
+}
+
gint
g_object_info_get_n_constants (GIObjectInfo *info)
{
@@ -1728,6 +1785,34 @@ g_interface_info_get_vfunc (GIInterfaceInfo *info,
base->typelib, offset);
}
+/**
+ * g_interface_info_find_vfunc:
+ * @info: An #GIObjectInfo
+ * @name: The name of a virtual function to find.
+ *
+ * Locate a virtual function slot with name @name. See the documentation
+ * for #g_object_info_find_vfunc for more information on virtuals.
+ *
+ * Return value: (transfer full): A #GIVFuncInfo, or %NULL if none with name @name.
+ */
+GIVFuncInfo *
+g_interface_info_find_vfunc (GIInterfaceInfo *info,
+ const gchar *name)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->typelib->data;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->typelib->data[base->offset];
+
+ offset = base->offset + header->interface_blob_size
+ + (blob->n_prerequisites + blob->n_prerequisites % 2) * 2
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + blob->n_signals * header->signal_blob_size;
+
+ return find_vfunc (base, offset, blob->n_vfuncs, name);
+}
+
gint
g_interface_info_get_n_constants (GIInterfaceInfo *info)
{
@@ -1913,6 +1998,37 @@ g_vfunc_info_get_signal (GIVFuncInfo *info)
return NULL;
}
+/**
+ * g_vfunc_info_get_invoker:
+ * @info: A #GIVFuncInfo
+ *
+ * If this virtual function has an associated invoker method, this
+ * method will return it. An invoker method is a C entry point.
+ *
+ * Not all virtuals will have invokers.
+ *
+ * Return value: (transfer full): An invoker function, or %NULL if none known
+ */
+GIFunctionInfo *
+g_vfunc_info_get_invoker (GIVFuncInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ VFuncBlob *blob = (VFuncBlob *)&base->typelib->data[base->offset];
+ GIBaseInfo *container = base->container;
+ GIInfoType parent_type;
+
+ /* 1023 = 0x3ff is the maximum of the 10 bits for invoker index */
+ if (blob->invoker == 1023)
+ return NULL;
+
+ parent_type = g_base_info_get_type (container);
+ if (parent_type == GI_INFO_TYPE_OBJECT)
+ return g_object_info_get_method ((GIObjectInfo*)container, blob->invoker);
+ else if (parent_type == GI_INFO_TYPE_INTERFACE)
+ return g_interface_info_get_method ((GIInterfaceInfo*)container, blob->invoker);
+ else
+ g_assert_not_reached ();
+}
/* GIConstantInfo functions */
GITypeInfo *
diff --git a/girepository/girepository.h b/girepository/girepository.h
index 4059adc..1058570 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -470,6 +470,8 @@ GISignalInfo * g_object_info_get_signal (GIObjectInfo *in
gint g_object_info_get_n_vfuncs (GIObjectInfo *info);
GIVFuncInfo * g_object_info_get_vfunc (GIObjectInfo *info,
gint n);
+GIVFuncInfo * g_object_info_find_vfunc (GIObjectInfo *info,
+ const gchar *name);
gint g_object_info_get_n_constants (GIObjectInfo *info);
GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info,
gint n);
@@ -495,6 +497,8 @@ GISignalInfo * g_interface_info_get_signal (GIInterfaceInfo *in
gint g_interface_info_get_n_vfuncs (GIInterfaceInfo *info);
GIVFuncInfo * g_interface_info_get_vfunc (GIInterfaceInfo *info,
gint n);
+GIVFuncInfo * g_interface_info_find_vfunc (GIInterfaceInfo *info,
+ const gchar *name);
gint g_interface_info_get_n_constants (GIInterfaceInfo *info);
GIConstantInfo * g_interface_info_get_constant (GIInterfaceInfo *info,
gint n);
@@ -527,6 +531,7 @@ typedef enum
GIVFuncInfoFlags g_vfunc_info_get_flags (GIVFuncInfo *info);
gint g_vfunc_info_get_offset (GIVFuncInfo *info);
GISignalInfo * g_vfunc_info_get_signal (GIVFuncInfo *info);
+GIFunctionInfo * g_vfunc_info_get_invoker (GIVFuncInfo *info);
/* GIConstantInfo */
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 22c0aee..01e83ac 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -265,6 +265,7 @@ g_ir_node_free (GIrNode *node)
GIrNodeVFunc *vfunc = (GIrNodeVFunc *)node;
g_free (node->name);
+ g_free (vfunc->invoker);
for (l = vfunc->parameters; l; l = l->next)
g_ir_node_free ((GIrNode *)l->data);
g_list_free (vfunc->parameters);
@@ -1186,6 +1187,30 @@ g_ir_find_node (GIrModule *module,
return node != NULL;
}
+static int
+get_index_of_member_type (GIrNodeInterface *node,
+ GIrNodeTypeId type,
+ const char *name)
+{
+ guint index = -1;
+ GList *l;
+
+ for (l = node->members; l; l = l->next)
+ {
+ GIrNode *node = l->data;
+
+ if (node->type != type)
+ continue;
+
+ index++;
+
+ if (strcmp (node->name, name) == 0)
+ break;
+ }
+
+ return index;
+}
+
static void
serialize_type (GIrModule *module,
GList *modules,
@@ -1759,6 +1784,18 @@ g_ir_node_build_typelib (GIrNode *node,
blob->class_closure = 0; /* FIXME */
blob->reserved = 0;
+ if (vfunc->invoker)
+ {
+ int index = get_index_of_member_type ((GIrNodeInterface*)parent, G_IR_NODE_FUNCTION, vfunc->invoker);
+ if (index == -1)
+ {
+ g_error ("Unknown member function %s for vfunc %s", vfunc->invoker, node->name);
+ }
+ blob->invoker = (guint) index;
+ }
+ else
+ blob->invoker = 0x3ff; /* max of 10 bits */
+
blob->struct_offset = vfunc->offset;
blob->reserved2 = 0;
blob->signature = signature;
diff --git a/girepository/girnode.h b/girepository/girnode.h
index 2a1f6b2..238593a 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -214,6 +214,8 @@ struct _GIrNodeVFunc
gboolean must_not_be_implemented;
gboolean is_class_closure;
+ char *invoker;
+
GList *parameters;
GIrNodeParam *result;
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 006ed3b..9afd858 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -2080,7 +2080,7 @@ start_vfunc (GMarkupParseContext *context,
ParseContext *ctx,
GError **error)
{
- if (strcmp (element_name, "vfunc") == 0 &&
+ if (strcmp (element_name, "virtual-method") == 0 &&
(ctx->state == STATE_CLASS ||
ctx->state == STATE_INTERFACE))
{
@@ -2089,12 +2089,14 @@ start_vfunc (GMarkupParseContext *context,
const gchar *override;
const gchar *is_class_closure;
const gchar *offset;
+ const gchar *invoker;
name = find_attribute ("name", attribute_names, attribute_values);
must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
override = find_attribute ("override", attribute_names, attribute_values);
is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
offset = find_attribute ("offset", attribute_names, attribute_values);
+ invoker = find_attribute ("invoker", attribute_names, attribute_values);
if (name == NULL)
MISSING_ATTRIBUTE (context, error, element_name, "name");
@@ -2138,6 +2140,8 @@ start_vfunc (GMarkupParseContext *context,
else
vfunc->offset = 0;
+ vfunc->invoker = g_strdup (invoker);
+
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
iface->members = g_list_append (iface->members, vfunc);
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index db5fe11..f6ad8c9 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -843,9 +843,10 @@ typedef struct {
* @class_closure: Set if this virtual function is the class closure of a signal.
* @signal: The index of the signal in the list of signals of the object or
* interface to which this virtual function belongs.
- * @struct_offset:
- * The offset of the function pointer in the class struct. The value
+ * @struct_offset: The offset of the function pointer in the class struct. The value
* 0xFFFF indicates that the struct offset is unknown.
+ * @invoker: If a method invoker for this virtual exists, this is the offset in the
+ * class structure of the method. If no method is known, this value will be 0x3ff.
* @signature:
* Offset of the SignatureBlob describing the parameter types and the
* return value type.
@@ -861,7 +862,8 @@ typedef struct {
guint16 signal;
guint16 struct_offset;
- guint16 reserved2;
+ guint16 invoker : 10; /* Number of bits matches @index in FunctionBlob */
+ guint16 reserved2 : 6;
guint32 reserved3;
guint32 signature;
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 35300b0..f32486c 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -41,6 +41,7 @@ from .glibast import GLibBoxed
_COMMENT_HEADER = '*\n '
# Tags - annotations applyed to comment blocks
+TAG_VFUNC = 'virtual'
TAG_SINCE = 'since'
TAG_DEPRECATED = 'deprecated'
TAG_RETURNS = 'returns'
@@ -298,8 +299,9 @@ class AnnotationApplier(object):
block = self._blocks.get(class_.type_name)
self._parse_node_common(class_, block)
self._parse_constructors(class_.constructors)
- self._parse_methods(class_.methods)
- self._parse_methods(class_.static_methods)
+ self._parse_methods(class_, class_.methods)
+ self._parse_vfuncs(class_, class_.virtual_methods)
+ self._parse_methods(class_, class_.static_methods)
self._parse_properties(class_, class_.properties)
self._parse_signals(class_, class_.signals)
self._parse_fields(class_, class_.fields)
@@ -309,7 +311,8 @@ class AnnotationApplier(object):
def _parse_interface(self, interface):
block = self._blocks.get(interface.type_name)
self._parse_node_common(interface, block)
- self._parse_methods(interface.methods)
+ self._parse_methods(interface, interface.methods)
+ self._parse_vfuncs(interface, interface.virtual_methods)
self._parse_properties(interface, interface.properties)
self._parse_signals(interface, interface.signals)
self._parse_fields(interface, interface.fields)
@@ -320,7 +323,7 @@ class AnnotationApplier(object):
block = self._blocks.get(record.symbol)
self._parse_node_common(record, block)
self._parse_constructors(record.constructors)
- self._parse_methods(record.methods)
+ self._parse_methods(record, record.methods)
self._parse_fields(record, record.fields)
if block:
record.doc = block.comment
@@ -329,7 +332,7 @@ class AnnotationApplier(object):
block = self._blocks.get(boxed.name)
self._parse_node_common(boxed, block)
self._parse_constructors(boxed.constructors)
- self._parse_methods(boxed.methods)
+ self._parse_methods(boxed, boxed.methods)
if block:
boxed.doc = block.comment
@@ -338,7 +341,7 @@ class AnnotationApplier(object):
self._parse_node_common(union, block)
self._parse_fields(union, union.fields)
self._parse_constructors(union.constructors)
- self._parse_methods(union.methods)
+ self._parse_methods(union, union.methods)
if block:
union.doc = block.comment
@@ -370,9 +373,13 @@ class AnnotationApplier(object):
for prop in properties:
self._parse_property(parent, prop)
- def _parse_methods(self, methods):
+ def _parse_methods(self, parent, methods):
for method in methods:
- self._parse_function(method)
+ self._parse_method(parent, method)
+
+ def _parse_vfuncs(self, parent, vfuncs):
+ for vfunc in vfuncs:
+ self._parse_vfunc(parent, vfunc)
def _parse_signals(self, parent, signals):
for signal in signals:
@@ -392,18 +399,20 @@ class AnnotationApplier(object):
if block:
callback.doc = block.comment
+ def _parse_callable(self, callable, block):
+ self._parse_node_common(callable, block)
+ self._parse_params(callable, callable.parameters, block)
+ self._parse_return(callable, callable.retval, block)
+ if block:
+ callable.doc = block.comment
+
def _parse_function(self, func):
block = self._blocks.get(func.symbol)
- self._parse_node_common(func, block)
- self._parse_params(func, func.parameters, block)
- self._parse_return(func, func.retval, block)
- if block:
- func.doc = block.comment
+ self._parse_callable(func, block)
def _parse_signal(self, parent, signal):
block = self._blocks.get('%s::%s' % (parent.type_name, signal.name))
self._parse_node_common(signal, block)
- self._parse_deprecated(signal, block)
# We're only attempting to name the signal parameters if
# the number of parameter tags (@foo) is the same or greater
# than the number of signal parameters
@@ -426,6 +435,26 @@ class AnnotationApplier(object):
if block:
signal.doc = block.comment
+ def _parse_method(self, parent, meth):
+ block = self._blocks.get(meth.symbol)
+ self._parse_function(meth)
+ virtual = self._get_tag(block, TAG_VFUNC)
+ if virtual:
+ invoker_name = virtual.value
+ matched = False
+ for vfunc in parent.virtual_methods:
+ if vfunc.name == invoker_name:
+ matched = True
+ vfunc.invoker = meth.name
+ break
+ if not matched:
+ print "warning: unmatched virtual invoker %r for method %r" % \
+ (invoker_name, meth.symbol)
+
+ def _parse_vfunc(self, parent, vfunc):
+ key = '%s::%s' % (parent.type_name, vfunc.name)
+ self._parse_callable(vfunc, self._blocks.get(key))
+
def _parse_field(self, parent, field):
if isinstance(field, Callback):
self._parse_callback(field)
diff --git a/giscanner/ast.py b/giscanner/ast.py
index d2bae87..0f0d1bb 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -196,15 +196,25 @@ class Include(Node):
def __str__(self):
return '%s-%s' % (self.name, self.version)
+class Callable(Node):
-class Function(Node):
-
- def __init__(self, name, retval, parameters, symbol, throws=None):
+ def __init__(self, name, retval, parameters, throws):
Node.__init__(self, name)
self.retval = retval
self.parameters = parameters
- self.symbol = symbol
self.throws = not not throws
+ self.doc = None
+
+ def __repr__(self):
+ return '%s(%r, %r, %r)' % (self.__class__.__name__,
+ self.name, self.retval,
+ self.parameters)
+
+class Function(Callable):
+
+ def __init__(self, name, retval, parameters, symbol, throws=None):
+ Callable.__init__(self, name, retval, parameters, throws)
+ self.symbol = symbol
self.is_method = False
self.doc = None
@@ -218,14 +228,18 @@ class Function(Node):
if parameter.name == name:
return parameter
- def __repr__(self):
- return '%s(%r, %r, %r)' % (self.__class__.__name__,
- self.name, self.retval,
- self.parameters)
+class VFunction(Callable):
-class VFunction(Function):
- pass
+ def __init__(self, name, retval, parameters, throws):
+ Callable.__init__(self, name, retval, parameters, throws)
+ self.invoker = None
+
+ @classmethod
+ def from_callback(cls, cb):
+ obj = cls(cb.name, cb.retval, cb.parameters[1:],
+ cb.throws)
+ return obj
class Type(Node):
@@ -411,6 +425,7 @@ class Class(Node):
self.glib_type_struct = None
self.is_abstract = is_abstract
self.methods = []
+ self.virtual_methods = []
self.static_methods = []
self.interfaces = []
self.constructors = []
@@ -430,6 +445,7 @@ class Interface(Node):
Node.__init__(self, name)
self.parent = parent
self.methods = []
+ self.virtual_methods = []
self.glib_type_struct = None
self.properties = []
self.fields = []
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 88510b0..e30bc6b 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -158,18 +158,22 @@ and/or use gtk-doc annotations. ''')
attrs.append(('c:type', alias.ctype))
self.write_tag('alias', attrs)
- def _write_function(self, func, tag_name='function'):
- attrs = [('name', func.name),
- ('c:identifier', func.symbol)]
- if func.doc:
- attrs.append(('doc', func.doc))
- self._append_version(func, attrs)
- self._append_deprecated(func, attrs)
- self._append_throws(func, attrs)
+ def _write_callable(self, callable, tag_name, extra_attrs):
+ attrs = [('name', callable.name)]
+ attrs.extend(extra_attrs)
+ if callable.doc:
+ attrs.append(('doc', callable.doc))
+ self._append_version(callable, attrs)
+ self._append_deprecated(callable, attrs)
+ self._append_throws(callable, attrs)
with self.tagcontext(tag_name, attrs):
- self._write_attributes(func)
- self._write_return_type(func.retval)
- self._write_parameters(func.parameters)
+ self._write_attributes(callable)
+ self._write_return_type(callable.retval)
+ self._write_parameters(callable.parameters)
+
+ def _write_function(self, func, tag_name='function'):
+ attrs = [('c:identifier', func.symbol)]
+ self._write_callable(func, tag_name, attrs)
def _write_method(self, method):
self._write_function(method, tag_name='method')
@@ -354,6 +358,8 @@ and/or use gtk-doc annotations. ''')
self._write_constructor(method)
for method in node.static_methods:
self._write_static_method(method)
+ for vfunc in node.virtual_methods:
+ self._write_vfunc(vfunc)
for method in node.methods:
self._write_method(method)
for prop in node.properties:
@@ -395,18 +401,15 @@ and/or use gtk-doc annotations. ''')
self._write_attributes(prop)
self._write_type(prop.type)
+ def _write_vfunc(self, vf):
+ attrs = []
+ if vf.invoker:
+ attrs.append(('invoker', vf.invoker))
+ self._write_callable(vf, 'virtual-method', attrs)
+
def _write_callback(self, callback):
- # FIXME: reuse _write_function
- attrs = [('name', callback.name), ('c:type', callback.ctype)]
- if callback.doc:
- attrs.append(('doc', callback.doc))
- self._append_version(callback, attrs)
- self._append_deprecated(callback, attrs)
- self._append_throws(callback, attrs)
- with self.tagcontext('callback', attrs):
- self._write_attributes(callback)
- self._write_return_type(callback.retval)
- self._write_parameters(callback.parameters)
+ attrs = [('c:type', callback.ctype)]
+ self._write_callable(callback, 'callback', attrs)
def _boxed_attrs(self, boxed):
return [('glib:type-name', boxed.type_name),
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 5a7a96d..61d4cef 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -27,12 +27,13 @@ import subprocess
from .ast import (Alias, Bitfield, Callback, Constant, Enum, Function, Member,
Namespace, Parameter, Property, Record, Return, Type, Union,
- Field, type_name_from_ctype,
+ Field, VFunction, type_name_from_ctype,
default_array_types, TYPE_UINT8, PARAM_TRANSFER_FULL)
from .transformer import Names
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
- GLibBoxedUnion, GLibBoxedOther, GLibRecord, type_names)
+ GLibBoxedUnion, GLibBoxedOther, GLibRecord,
+ type_names)
from .utils import to_underscores, to_underscores_noprefix
default_array_types['guchar*'] = TYPE_UINT8
@@ -159,6 +160,10 @@ class GLibTransformer(object):
except KeyError, e:
print "WARNING: DELETING node %s: %s" % (node.name, e)
self._remove_attribute(node.name)
+ # Another pass, since we need to have the methods parsed
+ # in order to correctly modify them after class/record
+ # pairing
+ for (ns, node) in nodes:
# associate GtkButtonClass with GtkButton
if isinstance(node, Record):
self._pair_class_record(node)
@@ -167,7 +172,9 @@ class GLibTransformer(object):
self._resolve_quarks()
# Fourth pass: ensure all types are known
if not self._noclosure:
- self._validate(nodes)
+ self._resolve_types(nodes)
+
+ self._validate(nodes)
# Create a new namespace with what we found
namespace = Namespace(self._namespace_name, self._namespace_version)
@@ -573,10 +580,43 @@ class GLibTransformer(object):
for field in maybe_class.fields:
if isinstance(field, Field):
field.writable = False
- # TODO: remove this, we should be computing vfuncs instead
- if isinstance(pair_class, GLibInterface):
- for field in maybe_class.fields[1:]:
- pair_class.fields.append(field)
+
+ # Loop through fields to determine which are virtual
+ # functions and which are signal slots by
+ # assuming everything that doesn't share a name
+ # with a known signal is a virtual slot.
+ for field in maybe_class.fields:
+ if not isinstance(field, Callback):
+ continue
+ # Check the first parameter is the object
+ if len(field.parameters) == 0:
+ continue
+ firstparam_type = field.parameters[0].type
+ if firstparam_type != pair_class:
+ continue
+ # Also double check we don't have a signal with this
+ # name.
+ matched_signal = False
+ for signal in pair_class.signals:
+ if signal.name.replace('-', '_') == field.name:
+ matched_signal = True
+ break
+ if matched_signal:
+ continue
+ vfunc = VFunction.from_callback(field)
+ pair_class.virtual_methods.append(vfunc)
+
+ # Take the set of virtual methods we found, and try
+ # to pair up with any matching methods using the
+ # name+signature.
+ for vfunc in pair_class.virtual_methods:
+ for method in pair_class.methods:
+ if (method.name != vfunc.name or
+ method.retval != vfunc.retval or
+ method.parameters != vfunc.parameters):
+ continue
+ vfunc.invoker = method.name
+
gclass_struct = GLibRecord.from_record(class_struct)
self._remove_attribute(class_struct.name)
self._add_attribute(gclass_struct, True)
@@ -903,9 +943,7 @@ class GLibTransformer(object):
def _resolve_alias(self, alias):
alias.target = self._resolve_type_name(alias.target, alias.target)
- # Validation
-
- def _validate(self, nodes):
+ def _resolve_types(self, nodes):
nodes = list(self._names.names.itervalues())
i = 0
self._validating = True
@@ -925,3 +963,18 @@ class GLibTransformer(object):
i += 1
self._print_statistics()
self._validating = False
+
+ # Validation
+
+ def _validate_interface(self, iface):
+ for vfunc in iface.virtual_methods:
+ if not vfunc.invoker:
+ print ("warning: Interface %r virtual function %r " + \
+ "has no known invoker") % (iface.name, vfunc.name)
+
+ # This function is called at the very end, before we hand back the
+ # completed namespace to the writer. Add static analysis checks here.
+ def _validate(self, nodes):
+ for (name, node) in nodes:
+ if isinstance(node, GLibInterface):
+ self._validate_interface(node)
diff --git a/tests/everything/everything.c b/tests/everything/everything.c
index 75842bf..c597f85 100644
--- a/tests/everything/everything.c
+++ b/tests/everything/everything.c
@@ -789,6 +789,12 @@ test_obj_dispose (GObject *gobject)
G_OBJECT_CLASS (test_obj_parent_class)->dispose (gobject);
}
+static int
+test_obj_default_matrix (TestObj *obj, const char *somestr)
+{
+ return 42;
+}
+
static void
test_obj_class_init (TestObjClass *klass)
{
@@ -819,6 +825,8 @@ test_obj_class_init (TestObjClass *klass)
g_object_class_install_property (gobject_class,
PROP_TEST_OBJ_BARE,
pspec);
+
+ klass->matrix = test_obj_default_matrix;
}
static void
@@ -854,6 +862,23 @@ test_obj_static_method (int x)
}
/**
+ * test_obj_do_matrix:
+ * @obj: A #TestObj
+ * @somestr: Meaningless string
+ *
+ * This method is virtual. Notably its name differs from the virtual
+ * slot name, which makes it useful for testing bindings handle this
+ * case.
+ *
+ * Virtual: matrix
+ */
+int
+test_obj_do_matrix (TestObj *obj, const char *somestr)
+{
+ return TEST_OBJ_GET_CLASS (obj)->matrix (obj, somestr);
+}
+
+/**
* test_callback:
* @callback: (scope call):
*
diff --git a/tests/everything/everything.h b/tests/everything/everything.h
index dbb7995..2474566 100644
--- a/tests/everything/everything.h
+++ b/tests/everything/everything.h
@@ -178,6 +178,7 @@ gboolean test_boxed_equals (TestBoxed *boxed,
#define TEST_TYPE_OBJ (test_obj_get_type ())
#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJ, TestObj))
#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJ))
+#define TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJ, TestObjClass))
typedef struct _TestObj TestObj;
typedef struct _TestObjClass TestObjClass;
@@ -197,6 +198,8 @@ struct _TestObjClass
{
GObjectClass parent_class;
+ int (*matrix) (TestObj *obj, const char *somestr);
+
guint test_signal;
};
@@ -205,6 +208,9 @@ TestObj* test_obj_new_from_file (const char *x, GError **error);
void test_obj_set_bare (TestObj *obj, GObject *bare);
double test_obj_static_method (int x);
+/* virtual */
+int test_obj_do_matrix (TestObj *obj, const char *somestr);
+
/* callback */
typedef int (*TestCallback) ();
typedef int (*TestCallbackUserData) (gpointer user_data);
diff --git a/tests/repository/Makefile.am b/tests/repository/Makefile.am
index e21cff4..36f738d 100644
--- a/tests/repository/Makefile.am
+++ b/tests/repository/Makefile.am
@@ -13,5 +13,5 @@ gitestthrows_CPPFLAGS = $(GIREPO_CFLAGS) -I$(top_srcdir)/girepository
gitestthrows_LDADD = $(top_builddir)/girepository/libgirepository-1.0.la $(GIREPO_LIBS)
TESTS = gitestrepo gitestthrows
-TESTS_ENVIRONMENT=env top_builddir="$(top_builddir)" $(DEBUG) \
- XDG_DATA_DIRS="$(top_srcdir)/gir:$(XDG_DATA_DIRS)"
+TESTS_ENVIRONMENT=env top_builddir="$(top_builddir)" \
+ XDG_DATA_DIRS="$(top_srcdir)/gir:$(XDG_DATA_DIRS)" $(DEBUG) \ No newline at end of file
diff --git a/tests/repository/gitestrepo.c b/tests/repository/gitestrepo.c
index 0e67467..a65116b 100644
--- a/tests/repository/gitestrepo.c
+++ b/tests/repository/gitestrepo.c
@@ -73,5 +73,53 @@ main(int argc, char **argv)
info = g_irepository_find_by_name (repo, "Gio", "ThisDoesNotExist");
g_assert (info == NULL);
+ /* vfunc tests */
+ {
+ GIVFuncInfo *vfunc;
+ GIFunctionInfo *invoker;
+
+ /* Test vfunc with invoker on interface */
+ info = g_irepository_find_by_name (repo, "Gio", "File");
+ g_assert (info != NULL);
+
+ vfunc = g_interface_info_find_vfunc ((GIInterfaceInfo*)info, "read_async");
+ g_assert (vfunc != NULL);
+
+ invoker = g_vfunc_info_get_invoker (vfunc);
+ g_assert (invoker != NULL);
+
+ g_assert (strcmp (g_base_info_get_name ((GIBaseInfo*)invoker), "read_async") == 0);
+
+ /* Test vfunc with no known invoker on object */
+ info = g_irepository_find_by_name (repo, "GObject", "Object");
+ g_assert (info != NULL);
+
+ vfunc = g_object_info_find_vfunc ((GIObjectInfo*)info, "dispose");
+ g_assert (vfunc != NULL);
+
+ /* Ok, maybe we should mark g_object_run_dispose as the invoker for
+ * dispose, but...eh. It's pretty special however you cut it.
+ */
+ invoker = g_vfunc_info_get_invoker (vfunc);
+ g_assert (invoker == NULL);
+
+ /* Test vfunc with invoker on object */
+ info = g_irepository_find_by_name (repo, "Gio", "AppLaunchContext");
+ g_assert (info != NULL);
+
+ vfunc = g_object_info_find_vfunc ((GIObjectInfo*)info, "get_display");
+ g_assert (vfunc != NULL);
+
+ invoker = g_vfunc_info_get_invoker (vfunc);
+ g_assert (invoker != NULL);
+ g_assert (strcmp (g_base_info_get_name ((GIBaseInfo*)invoker), "get_display") == 0);
+
+ /* And let's be sure we can find the method directly */
+
+ invoker = g_object_info_find_method ((GIObjectInfo*)info, "get_display");
+ g_assert (invoker != NULL);
+ g_assert (strcmp (g_base_info_get_name ((GIBaseInfo*)invoker), "get_display") == 0);
+ }
+
exit(0);
}
diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir
index 0f6b1f1..086170e 100644
--- a/tests/scanner/foo-1.0-expected.gir
+++ b/tests/scanner/foo-1.0-expected.gir
@@ -232,16 +232,26 @@ and/or use gtk-doc annotations. -->
glib:type-name="FooInterface"
glib:get-type="foo_interface_get_type"
glib:type-struct="InterfaceIface">
- <callback name="do_foo" c:type="do_foo">
+ <virtual-method name="do_foo" invoker="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 name="x" transfer-ownership="none">
+ <type name="int" c:type="int"/>
</parameter>
</parameters>
- </callback>
+ </virtual-method>
+ <method name="do_foo" c:identifier="foo_interface_do_foo">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="x" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ </parameters>
+ </method>
</interface>
<record name="InterfaceIface"
c:type="FooInterfaceIface"
@@ -257,6 +267,9 @@ and/or use gtk-doc annotations. -->
<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>
</record>
@@ -277,6 +290,29 @@ and/or use gtk-doc annotations. -->
<type name="int" c:type="int"/>
</return-value>
</function>
+ <virtual-method name="virtual_method" invoker="virtual_method">
+ <return-value transfer-ownership="none">
+ <type name="boolean" c:type="gboolean"/>
+ </return-value>
+ <parameters>
+ <parameter name="first_param" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ </parameters>
+ </virtual-method>
+ <virtual-method name="read_fn" invoker="read">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <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>
+ </virtual-method>
<method name="external_type" c:identifier="foo_object_external_type">
<return-value transfer-ownership="full">
<type name="utility.Object" c:type="UtilityObject*"/>
@@ -359,6 +395,31 @@ and/or use gtk-doc annotations. -->
</parameter>
</parameters>
</method>
+ <method name="virtual_method" c:identifier="foo_object_virtual_method">
+ <return-value transfer-ownership="none">
+ <type name="boolean" c:type="gboolean"/>
+ </return-value>
+ <parameters>
+ <parameter name="first_param" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ </parameters>
+ </method>
+ <method name="read"
+ c:identifier="foo_object_read"
+ doc="Read some stuff.">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <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>
+ </method>
<property name="string" writable="1" construct="1">
<type name="utf8" c:type="gchararray"/>
</property>
@@ -401,6 +462,22 @@ and/or use gtk-doc annotations. -->
</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>
</record>
<constant name="PIE_IS_TASTY" value="3.14159">
<type name="double"/>
@@ -467,21 +544,21 @@ and/or use gtk-doc annotations. -->
glib:get-type="foo_sub_interface_get_type"
glib:type-struct="SubInterfaceIface">
<prerequisite name="Interface"/>
+ <virtual-method name="do_bar" invoker="do_bar">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ </virtual-method>
<method name="do_bar" c:identifier="foo_sub_interface_do_bar">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
</method>
- <callback name="do_bar" c:type="do_bar">
- <return-value transfer-ownership="none">
+ <glib:signal name="destroy-event">
+ <return-value transfer-ownership="full">
<type name="none" c:type="void"/>
</return-value>
- <parameters>
- <parameter name="self" transfer-ownership="none">
- <type name="SubInterface" c:type="FooSubInterface*"/>
- </parameter>
- </parameters>
- </callback>
+ </glib:signal>
</interface>
<record name="SubInterfaceIface"
c:type="FooSubInterfaceIface"
@@ -489,6 +566,16 @@ and/or use gtk-doc annotations. -->
<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"/>
diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir
index f8e1ee5..1d82b6a 100644
--- a/tests/scanner/foo-1.0-expected.tgir
+++ b/tests/scanner/foo-1.0-expected.tgir
@@ -161,7 +161,28 @@
<member name="second" value="2"/>
<member name="third" value="4"/>
</bitfield>
- <interface name="Interface" glib:type-name="FooInterface" glib:get-type="foo_interface_get_type" glib:type-struct="InterfaceIface"/>
+ <interface name="Interface" glib:type-name="FooInterface" glib:get-type="foo_interface_get_type" glib:type-struct="InterfaceIface">
+ <method name="do_foo" c:identifier="foo_interface_do_foo">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="x" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </method>
+ <virtual-method name="do_foo" offset="0" invoker="do_foo">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="x" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </virtual-method>
+ </interface>
<record name="InterfaceIface" glib:is-gtype-struct="1">
<field name="parent_iface">
<type name="GObject.TypeInterface"/>
@@ -255,6 +276,29 @@
</parameter>
</parameters>
</method>
+ <method name="virtual_method" c:identifier="foo_object_virtual_method">
+ <return-value transfer-ownership="none">
+ <type name="boolean"/>
+ </return-value>
+ <parameters>
+ <parameter name="first_param" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </method>
+ <method name="read" c:identifier="foo_object_read">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="offset" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ <parameter name="length" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </method>
<property name="string" writable="1" construct="1">
<type name="utf8"/>
</property>
@@ -271,6 +315,29 @@
</parameter>
</parameters>
</glib:signal>
+ <virtual-method name="virtual_method" offset="0" invoker="virtual_method">
+ <return-value transfer-ownership="none">
+ <type name="boolean"/>
+ </return-value>
+ <parameters>
+ <parameter name="first_param" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </virtual-method>
+ <virtual-method name="read_fn" offset="0" invoker="read">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="offset" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ <parameter name="length" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </virtual-method>
</class>
<record name="ObjectClass" glib:is-gtype-struct="1">
<field name="parent_class">
@@ -342,6 +409,16 @@
<type name="none"/>
</return-value>
</method>
+ <glib:signal name="destroy-event" when="LAST">
+ <return-value transfer-ownership="full">
+ <type name="none"/>
+ </return-value>
+ </glib:signal>
+ <virtual-method name="do_bar" offset="0" invoker="do_bar">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ </virtual-method>
</interface>
<record name="SubInterfaceIface" glib:is-gtype-struct="1">
<field name="parent_iface">
diff --git a/tests/scanner/foo.c b/tests/scanner/foo.c
index 0488260..8a9283d 100644
--- a/tests/scanner/foo.c
+++ b/tests/scanner/foo.c
@@ -1,4 +1,5 @@
#include "foo.h"
+#include "girepository.h"
/* A hidden type not exposed publicly, similar to GUPNP's XML wrapper
object */
@@ -8,8 +9,8 @@ int foo_init_argv (int argc, char **argv);
int foo_init_argv_address (int *argc, char ***argv);
void foo_private_function (FooObject *foo);
void foo_test_unsigned (unsigned int uint);
-void foo_interface_do_foo (FooInterface *self);
-void foo_do_foo (FooInterface *self);
+void foo_interface_do_foo (FooInterface *self, int x);
+void foo_do_foo (FooInterface *self, int x);
int foo_enum_method (FooEnumType foo_enum);
FooHidden * foo_hidden_copy (const FooHidden *boxed);
void foo_hidden_free (FooHidden *boxed);
@@ -47,9 +48,9 @@ foo_interface_get_type (void)
return object_type;
}
-void foo_interface_do_foo (FooInterface *self)
+void foo_interface_do_foo (FooInterface *self, int x)
{
- FOO_INTERFACE_GET_INTERFACE(self)->do_foo (self);
+ FOO_INTERFACE_GET_INTERFACE(self)->do_foo (self, x);
}
enum {
@@ -73,6 +74,16 @@ foo_foo_interface_init (gpointer g_iface,
iface->do_foo = foo_do_foo;
}
+enum {
+ SUBIFACE_DESTROY_EVENT,
+ SUBIFACE_LAST_SIGNAL
+};
+
+static void
+foo_sub_interface_class_init (gpointer g_class, gpointer class_data);
+
+static guint foo_subiface_signals[SUBIFACE_LAST_SIGNAL] = { 0 };
+
GType
foo_sub_interface_get_type (void)
{
@@ -83,7 +94,7 @@ foo_sub_interface_get_type (void)
object_type = g_type_register_static_simple (G_TYPE_INTERFACE,
"FooSubInterface",
sizeof (FooSubInterfaceIface),
- NULL, 0, NULL, 0);
+ foo_sub_interface_class_init, 0, NULL, 0);
g_type_interface_add_prerequisite (object_type, FOO_TYPE_INTERFACE);
}
@@ -91,6 +102,20 @@ foo_sub_interface_get_type (void)
return object_type;
}
+static void
+foo_sub_interface_class_init (gpointer g_class, gpointer class_data)
+{
+ foo_subiface_signals[SUBIFACE_DESTROY_EVENT] =
+ g_signal_new ("destroy-event", FOO_TYPE_SUBINTERFACE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (FooSubInterfaceIface, destroy_event),
+ NULL, NULL,
+ gi_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 0,
+ G_TYPE_NONE);
+}
+
void foo_sub_interface_do_bar (FooSubInterface *self)
{
FOO_SUBINTERFACE_GET_INTERFACE(self)->do_bar (self);
@@ -191,7 +216,7 @@ foo_object_take_all (FooObject *object, int x, ...)
}
void
-foo_do_foo (FooInterface *self)
+foo_do_foo (FooInterface *self, int x)
{
@@ -214,6 +239,22 @@ foo_object_dup_name (FooObject *object)
return g_strdup ("foo");
}
+/**
+ * foo_object_read:
+ * @object: obj
+ * @offset: offset
+ * @length: length
+ *
+ * Read some stuff.
+ *
+ * Virtual: read_fn
+ */
+void
+foo_object_read (FooObject *object, int offset, int length)
+{
+
+}
+
G_DEFINE_ABSTRACT_TYPE (FooSubobject, foo_subobject, FOO_TYPE_OBJECT);
static void
diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h
index da30df3..02f3cfe 100644
--- a/tests/scanner/foo.h
+++ b/tests/scanner/foo.h
@@ -48,15 +48,23 @@ struct _FooInterfaceIface
{
GTypeInterface parent_iface;
- void (*do_foo) (FooInterface *self);
+ void (*do_foo) (FooInterface *self, int x);
};
GType foo_interface_get_type (void) G_GNUC_CONST;
+void foo_interface_do_foo (FooInterface *iface, int x);
+
struct _FooSubInterfaceIface
{
GTypeInterface parent_iface;
+ /* signals */
+
+ void (*destroy_event) (FooSubInterface *self);
+
+ /* virtual table */
+
void (*do_bar) (FooSubInterface *self);
};
@@ -76,6 +84,9 @@ struct _FooObjectClass
GObjectClass parent_class;
gboolean (* virtual_method) (FooObject *object, int first_param);
+
+ /* Intended to match GFile */
+ void (*read_fn) (FooObject *object, int offset, int length);
};
gint foo_init (void);
@@ -105,6 +116,10 @@ char * foo_object_dup_name (FooObject *object);
void foo_object_handle_glyph (FooObject *object, UtilityGlyph glyph);
+gboolean foo_object_virtual_method (FooObject *object, int first_param);
+
+void foo_object_read (FooObject *object, int offset, int length);
+
int foo_object_static_meth ();
struct _FooSubobject
diff --git a/tools/generate.c b/tools/generate.c
index c4d7291..48d7dfb 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -869,6 +869,7 @@ write_vfunc_info (const gchar *namespace,
{
GIVFuncInfoFlags flags;
const gchar *name;
+ GIFunctionInfo *invoker;
gboolean deprecated;
gint offset;
@@ -876,8 +877,9 @@ write_vfunc_info (const gchar *namespace,
flags = g_vfunc_info_get_flags (info);
deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
offset = g_vfunc_info_get_offset (info);
+ invoker = g_vfunc_info_get_invoker (info);
- xml_start_element (file, "vfunc");
+ xml_start_element (file, "virtual-method");
xml_printf (file, " name=\"%s\"", name);
if (deprecated)
@@ -893,9 +895,12 @@ write_vfunc_info (const gchar *namespace,
xml_printf (file, " offset=\"%d\"", offset);
+ if (invoker)
+ xml_printf (file, " invoker=\"%s\"", g_base_info_get_name ((GIBaseInfo*)invoker));
+
write_callable_info (namespace, (GICallableInfo*)info, file);
- xml_end_element (file, "vfunc");
+ xml_end_element (file, "virtual-method");
}
static void