summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2009-02-27 19:02:48 -0500
committerColin Walters <walters@verbum.org>2009-03-05 15:52:12 -0500
commitfdbe3cc3e1cfaa546648a76b1dca72beead0b65b (patch)
tree01156e22ec59d29c642d59ce7ad75f383d77466a /tests
parentb8e3172424ba956a0d18eae8deb305310b2cab74 (diff)
downloadgobject-introspection-fdbe3cc3e1cfaa546648a76b1dca72beead0b65b.tar.gz
Bug 557383 - Virtual method support
Broadly speaking, this change adds the concept of <vfunc> to the .gir. The typelib already had most of the infrastructure for virtual functions, though there is one API addition. The scanner assumes that any class callback slot that doesn't match a signal name is a virtual. In the .gir, we write out *both* the <method> wrapper and a <vfunc>. If we can determine an association between them (based on the names matching, or a new Virtual: annotation), then we notate that in the .gir. The typelib gains an association from the vfunc to the function, if it exists. This will be useful for bindings since they already know how to consume FunctionInfo.
Diffstat (limited to 'tests')
-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
8 files changed, 321 insertions, 22 deletions
diff --git a/tests/everything/everything.c b/tests/everything/everything.c
index 75842bf3..c597f858 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 dbb7995e..2474566d 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 e21cff43..36f738d7 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 0e674670..a65116bc 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 0f6b1f1f..086170e5 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 f8e1ee59..1d82b6a3 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 04882603..8a9283d9 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 da30df38..02f3cfec 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