summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2010-06-12 18:08:56 -0300
committerJohan Dahlin <johan@gnome.org>2010-07-09 10:15:45 -0300
commit1e9822c7817062a9b853269b9418fd78782090b5 (patch)
tree684a6bc8520db45c9d126d954d7b82921cb2a753
parent017727630d09a854b1c1a4767066fb675b139de9 (diff)
downloadgobject-introspection-1e9822c7817062a9b853269b9418fd78782090b5.tar.gz
Add support for non-GObject fundamental objects
This patch adds support for instantiable fundamental object types, which are not GObject based. This is mostly interesting for being able to support GstMiniObject's which are extensivly used in GStreamer. Includes a big test case to the Everything module (inspired by GstMiniObject) which should be used by language bindings who wishes to test this functionallity. This patch increases the size of the typelib and breaks compatibility with older typelibs. https://bugzilla.gnome.org/show_bug.cgi?id=568913
-rw-r--r--docs/reference/gi-sections.txt13
-rw-r--r--gir/Everything-1.0-expected.gir101
-rw-r--r--gir/everything.c293
-rw-r--r--gir/everything.h55
-rw-r--r--girepository/gdump.c55
-rw-r--r--girepository/giobjectinfo.c249
-rw-r--r--girepository/giobjectinfo.h52
-rw-r--r--girepository/giregisteredtypeinfo.h3
-rw-r--r--girepository/girnode.c21
-rw-r--r--girepository/girnode.h6
-rw-r--r--girepository/girparser.c19
-rw-r--r--girepository/girwriter.c22
-rw-r--r--girepository/gitypelib-internal.h23
-rw-r--r--girepository/gitypelib.c2
-rw-r--r--giscanner/annotationparser.py15
-rw-r--r--giscanner/girwriter.py11
-rw-r--r--giscanner/glibast.py5
-rw-r--r--giscanner/glibtransformer.py32
18 files changed, 970 insertions, 7 deletions
diff --git a/docs/reference/gi-sections.txt b/docs/reference/gi-sections.txt
index 261afd81..6b04bbf7 100644
--- a/docs/reference/gi-sections.txt
+++ b/docs/reference/gi-sections.txt
@@ -144,9 +144,14 @@ g_interface_info_find_vfunc
<FILE>giobjectinfo</FILE>
GI_IS_OBJECT_INFO
GIObjectInfo
+GIObjectInfoGetValueFunction
+GIObjectInfoRefFunction
+GIObjectInfoSetValueFunction
+GIObjectInfoUnrefFunction
g_object_info_get_type_name
g_object_info_get_type_init
g_object_info_get_abstract
+g_object_info_get_fundamental
g_object_info_get_parent
g_object_info_get_n_interfaces
g_object_info_get_interface
@@ -165,6 +170,14 @@ g_object_info_get_n_constants
g_object_info_get_constant
g_object_info_get_class_struct
g_object_info_find_vfunc
+g_object_info_get_unref_function
+g_object_info_get_unref_function_pointer
+g_object_info_get_ref_function
+g_object_info_get_ref_function_pointer
+g_object_info_get_set_value_function
+g_object_info_get_set_value_function_pointer
+g_object_info_get_get_value_function
+g_object_info_get_get_value_function_pointer
</SECTION>
<SECTION>
diff --git a/gir/Everything-1.0-expected.gir b/gir/Everything-1.0-expected.gir
index 7fe9d1dc..4d3d2630 100644
--- a/gir/Everything-1.0-expected.gir
+++ b/gir/Everything-1.0-expected.gir
@@ -161,6 +161,107 @@ and/or use gtk-doc annotations. -->
c:type="GInitiallyUnownedClass"/>
</field>
</record>
+ <class name="TestFundamentalObject"
+ c:type="TestFundamentalObject"
+ abstract="1"
+ glib:type-name="TestFundamentalObject"
+ glib:get-type="test_fundamental_object_get_type"
+ glib:type-struct="TestFundamentalObjectClass"
+ glib:fundamental="1"
+ glib:ref-func="test_fundamental_object_ref"
+ glib:unref-func="test_fundamental_object_unref"
+ glib:set-value-func="test_value_set_fundamental_object"
+ glib:get-value-func="test_value_get_fundamental_object">
+ <method name="ref" c:identifier="test_fundamental_object_ref">
+ <return-value transfer-ownership="full">
+ <type name="TestFundamentalObject" c:type="TestFundamentalObject*"/>
+ </return-value>
+ </method>
+ <method name="unref" c:identifier="test_fundamental_object_unref">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ </method>
+ <field name="instance">
+ <type name="GObject.TypeInstance" c:type="GTypeInstance"/>
+ </field>
+ <field name="refcount">
+ <type name="int" c:type="gint"/>
+ </field>
+ <field name="flags">
+ <type name="uint" c:type="guint"/>
+ </field>
+ </class>
+ <record name="TestFundamentalObjectClass"
+ c:type="TestFundamentalObjectClass"
+ glib:is-gtype-struct-for="TestFundamentalObject">
+ <field name="type_class">
+ <type name="GObject.TypeClass" c:type="GTypeClass"/>
+ </field>
+ <field name="copy">
+ <type name="TestFundamentalObjectCopyFunction"
+ c:type="TestFundamentalObjectCopyFunction"/>
+ </field>
+ <field name="finalize">
+ <type name="TestFundamentalObjectFinalizeFunction"
+ c:type="TestFundamentalObjectFinalizeFunction"/>
+ </field>
+ </record>
+ <callback name="TestFundamentalObjectCopyFunction"
+ c:type="TestFundamentalObjectCopyFunction">
+ <return-value transfer-ownership="full">
+ <type name="TestFundamentalObject" c:type="TestFundamentalObject*"/>
+ </return-value>
+ <parameters>
+ <parameter name="obj" transfer-ownership="none">
+ <type name="TestFundamentalObject" c:type="TestFundamentalObject*"/>
+ </parameter>
+ </parameters>
+ </callback>
+ <callback name="TestFundamentalObjectFinalizeFunction"
+ c:type="TestFundamentalObjectFinalizeFunction">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="obj" transfer-ownership="none">
+ <type name="TestFundamentalObject" c:type="TestFundamentalObject*"/>
+ </parameter>
+ </parameters>
+ </callback>
+ <class name="TestFundamentalSubObject"
+ c:type="TestFundamentalSubObject"
+ parent="TestFundamentalObject"
+ glib:type-name="TestFundamentalSubObject"
+ glib:get-type="test_fundamental_sub_object_get_type"
+ glib:type-struct="TestFundamentalSubObjectClass"
+ glib:fundamental="1">
+ <constructor name="new" c:identifier="test_fundamental_sub_object_new">
+ <return-value transfer-ownership="full">
+ <type name="TestFundamentalSubObject"
+ c:type="TestFundamentalSubObject*"/>
+ </return-value>
+ <parameters>
+ <parameter name="data" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ </parameters>
+ </constructor>
+ <field name="fundamental_object">
+ <type name="TestFundamentalObject" c:type="TestFundamentalObject"/>
+ </field>
+ <field name="data">
+ <type name="utf8" c:type="char*"/>
+ </field>
+ </class>
+ <record name="TestFundamentalSubObjectClass"
+ c:type="TestFundamentalSubObjectClass"
+ glib:is-gtype-struct-for="TestFundamentalSubObject">
+ <field name="fundamental_object_class">
+ <type name="TestFundamentalObjectClass"
+ c:type="TestFundamentalObjectClass"/>
+ </field>
+ </record>
<interface name="TestInterface"
c:type="EverythingTestInterface"
glib:type-name="EverythingTestInterface"
diff --git a/gir/everything.c b/gir/everything.c
index 2219667f..a2b4ef6c 100644
--- a/gir/everything.c
+++ b/gir/everything.c
@@ -1,5 +1,8 @@
#include <string.h>
#include <stdlib.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+
#include "everything.h"
static gboolean abort_on_error = TRUE;
@@ -1896,6 +1899,296 @@ test_sub_obj_unset_bare (TestSubObj *obj)
test_obj_set_bare(TEST_OBJECT(obj), NULL);
}
+/* TestFundamental */
+
+TestFundamentalObject *
+test_fundamental_object_ref (TestFundamentalObject * fundamental_object)
+{
+ g_return_val_if_fail (fundamental_object != NULL, NULL);
+ g_atomic_int_inc (&fundamental_object->refcount);
+
+ return fundamental_object;
+}
+
+static void
+test_fundamental_object_free (TestFundamentalObject * fundamental_object)
+{
+ TestFundamentalObjectClass *mo_class;
+ test_fundamental_object_ref (fundamental_object);
+
+ mo_class = TEST_FUNDAMENTAL_OBJECT_GET_CLASS (fundamental_object);
+ mo_class->finalize (fundamental_object);
+
+ if (G_LIKELY (g_atomic_int_dec_and_test (&fundamental_object->refcount))) {
+ g_type_free_instance ((GTypeInstance *) fundamental_object);
+ }
+}
+
+void
+test_fundamental_object_unref (TestFundamentalObject * fundamental_object)
+{
+ g_return_if_fail (fundamental_object != NULL);
+ g_return_if_fail (fundamental_object->refcount > 0);
+
+ if (G_UNLIKELY (g_atomic_int_dec_and_test (&fundamental_object->refcount))) {
+ test_fundamental_object_free (fundamental_object);
+ }
+}
+
+static void
+test_fundamental_object_replace (TestFundamentalObject ** olddata, TestFundamentalObject * newdata)
+{
+ TestFundamentalObject *olddata_val;
+
+ g_return_if_fail (olddata != NULL);
+
+ olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+
+ if (olddata_val == newdata)
+ return;
+
+ if (newdata)
+ test_fundamental_object_ref (newdata);
+
+ while (!g_atomic_pointer_compare_and_exchange ((gpointer *) olddata,
+ olddata_val, newdata)) {
+ olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
+ }
+
+ if (olddata_val)
+ test_fundamental_object_unref (olddata_val);
+}
+
+static void
+test_value_fundamental_object_init (GValue * value)
+{
+ value->data[0].v_pointer = NULL;
+}
+
+static void
+test_value_fundamental_object_free (GValue * value)
+{
+ if (value->data[0].v_pointer) {
+ test_fundamental_object_unref (TEST_FUNDAMENTAL_OBJECT_CAST (value->data[0].v_pointer));
+ }
+}
+
+static void
+test_value_fundamental_object_copy (const GValue * src_value, GValue * dest_value)
+{
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer =
+ test_fundamental_object_ref (TEST_FUNDAMENTAL_OBJECT_CAST (src_value->data[0].
+ v_pointer));
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+static gpointer
+test_value_fundamental_object_peek_pointer (const GValue * value)
+{
+ return value->data[0].v_pointer;
+}
+
+static gchar *
+test_value_fundamental_object_collect (GValue * value,
+ guint n_collect_values,
+ GTypeCValue * collect_values,
+ guint collect_flags)
+{
+ if (collect_values[0].v_pointer) {
+ value->data[0].v_pointer =
+ test_fundamental_object_ref (collect_values[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+
+ return NULL;
+}
+
+static gchar *
+test_value_fundamental_object_lcopy (const GValue * value,
+ guint n_collect_values,
+ GTypeCValue * collect_values,
+ guint collect_flags)
+{
+ gpointer *fundamental_object_p = collect_values[0].v_pointer;
+
+ if (!fundamental_object_p) {
+ return g_strdup_printf ("value location for '%s' passed as NULL",
+ G_VALUE_TYPE_NAME (value));
+ }
+
+ if (!value->data[0].v_pointer)
+ *fundamental_object_p = NULL;
+ else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+ *fundamental_object_p = value->data[0].v_pointer;
+ else
+ *fundamental_object_p = test_fundamental_object_ref (value->data[0].v_pointer);
+
+ return NULL;
+}
+
+static void
+test_fundamental_object_finalize (TestFundamentalObject * obj)
+{
+
+}
+
+static TestFundamentalObject *
+test_fundamental_object_copy_default (const TestFundamentalObject * obj)
+{
+ g_warning ("TestFundamentalObject classes must implement TestFundamentalObject::copy");
+ return NULL;
+}
+
+static void
+test_fundamental_object_class_init (gpointer g_class, gpointer class_data)
+{
+ TestFundamentalObjectClass *mo_class = TEST_FUNDAMENTAL_OBJECT_CLASS (g_class);
+
+ mo_class->copy = test_fundamental_object_copy_default;
+ mo_class->finalize = test_fundamental_object_finalize;
+}
+
+static void
+test_fundamental_object_init (GTypeInstance * instance, gpointer klass)
+{
+ TestFundamentalObject *fundamental_object = TEST_FUNDAMENTAL_OBJECT_CAST (instance);
+
+ fundamental_object->refcount = 1;
+}
+
+/**
+ * TestFundamentalObject:
+ *
+ * Ref Func: test_fundamental_object_ref
+ * Unref Func: test_fundamental_object_unref
+ * Set Value Func: test_value_set_fundamental_object
+ * Get Value Func: test_value_get_fundamental_object
+ */
+
+GType
+test_fundamental_object_get_type (void)
+{
+ static GType _test_fundamental_object_type = 0;
+
+ if (G_UNLIKELY (_test_fundamental_object_type == 0)) {
+ static const GTypeValueTable value_table = {
+ test_value_fundamental_object_init,
+ test_value_fundamental_object_free,
+ test_value_fundamental_object_copy,
+ test_value_fundamental_object_peek_pointer,
+ (char *) "p",
+ test_value_fundamental_object_collect,
+ (char *) "p",
+ test_value_fundamental_object_lcopy
+ };
+ static const GTypeInfo fundamental_object_info = {
+ sizeof (TestFundamentalObjectClass),
+ NULL, NULL,
+ test_fundamental_object_class_init,
+ NULL,
+ NULL,
+ sizeof (TestFundamentalObject),
+ 0,
+ (GInstanceInitFunc) test_fundamental_object_init,
+ &value_table
+ };
+ static const GTypeFundamentalInfo fundamental_object_fundamental_info = {
+ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE |
+ G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE)
+ };
+
+ _test_fundamental_object_type = g_type_fundamental_next ();
+ g_type_register_fundamental (_test_fundamental_object_type, "TestFundamentalObject",
+ &fundamental_object_info, &fundamental_object_fundamental_info, G_TYPE_FLAG_ABSTRACT);
+
+ }
+
+ return _test_fundamental_object_type;
+}
+
+/**
+ * test_value_set_fundamental_object: (skip)
+ * @value:
+ * @fundamental_object:
+ */
+void
+test_value_set_fundamental_object (GValue * value, TestFundamentalObject * fundamental_object)
+{
+ gpointer *pointer_p;
+
+ g_return_if_fail (TEST_VALUE_HOLDS_FUNDAMENTAL_OBJECT (value));
+ g_return_if_fail (fundamental_object == NULL || TEST_IS_FUNDAMENTAL_OBJECT (fundamental_object));
+
+ pointer_p = &value->data[0].v_pointer;
+
+ test_fundamental_object_replace ((TestFundamentalObject **) pointer_p, fundamental_object);
+}
+
+/**
+ * test_value_get_fundamental_object: (skip)
+ * @value:
+ */
+TestFundamentalObject *
+test_value_get_fundamental_object (const GValue * value)
+{
+ g_return_val_if_fail (TEST_VALUE_HOLDS_FUNDAMENTAL_OBJECT (value), NULL);
+
+ return value->data[0].v_pointer;
+}
+
+static TestFundamentalObjectClass *parent_class = NULL;
+
+G_DEFINE_TYPE (TestFundamentalSubObject, test_fundamental_sub_object, TEST_TYPE_FUNDAMENTAL_OBJECT);
+
+static TestFundamentalSubObject *
+_test_fundamental_sub_object_copy (TestFundamentalSubObject * fundamental_sub_object)
+{
+ TestFundamentalSubObject *copy;
+
+ copy = test_fundamental_sub_object_new(NULL);
+ copy->data = g_strdup(fundamental_sub_object->data);
+ return copy;
+}
+
+static void
+test_fundamental_sub_object_finalize (TestFundamentalSubObject * fundamental_sub_object)
+{
+ g_return_if_fail (fundamental_sub_object != NULL);
+
+ g_free(fundamental_sub_object->data);
+ test_fundamental_object_unref (TEST_FUNDAMENTAL_OBJECT (fundamental_sub_object));
+}
+
+static void
+test_fundamental_sub_object_class_init (TestFundamentalSubObjectClass * klass)
+{
+ parent_class = g_type_class_peek_parent (klass);
+
+ klass->fundamental_object_class.copy = (TestFundamentalObjectCopyFunction) _test_fundamental_sub_object_copy;
+ klass->fundamental_object_class.finalize =
+ (TestFundamentalObjectFinalizeFunction) test_fundamental_sub_object_finalize;
+}
+
+static void
+test_fundamental_sub_object_init(TestFundamentalSubObject *object)
+{
+
+}
+
+TestFundamentalSubObject *
+test_fundamental_sub_object_new (const char * data)
+{
+ TestFundamentalSubObject *object;
+
+ object = (TestFundamentalSubObject *) g_type_create_instance (test_fundamental_sub_object_get_type());
+ object->data = g_strdup(data);
+ return object;
+}
+
/**
* test_callback:
diff --git a/gir/everything.h b/gir/everything.h
index 8a8b1e0d..55b26cdf 100644
--- a/gir/everything.h
+++ b/gir/everything.h
@@ -334,6 +334,61 @@ TestSubObj* test_sub_obj_new (void);
void test_sub_obj_unset_bare (TestSubObj *obj);
int test_sub_obj_instance_method (TestSubObj *obj);
+/* fundamental object */
+#define TEST_TYPE_FUNDAMENTAL_OBJECT (test_fundamental_object_get_type())
+#define TEST_IS_FUNDAMENTAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_FUNDAMENTAL_OBJECT))
+#define TEST_IS_FUNDAMENTAL_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_FUNDAMENTAL_OBJECT))
+#define TEST_FUNDAMENTAL_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_FUNDAMENTAL_OBJECT, TestFundamentalObjectClass))
+#define TEST_FUNDAMENTAL_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_FUNDAMENTAL_OBJECT, TestFundamentalObject))
+#define TEST_FUNDAMENTAL_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_FUNDAMENTAL_OBJECT, TestFundamentalObjectClass))
+#define TEST_FUNDAMENTAL_OBJECT_CAST(obj) ((TestFundamentalObject*)(obj))
+
+typedef struct _TestFundamentalObject TestFundamentalObject;
+typedef struct _TestFundamentalObjectClass TestFundamentalObjectClass;
+typedef TestFundamentalObject * (*TestFundamentalObjectCopyFunction) (const TestFundamentalObject *obj);
+typedef void (*TestFundamentalObjectFinalizeFunction) (TestFundamentalObject *obj);
+
+
+struct _TestFundamentalObject {
+ GTypeInstance instance;
+ gint refcount;
+ guint flags;
+};
+
+struct _TestFundamentalObjectClass {
+ GTypeClass type_class;
+
+ TestFundamentalObjectCopyFunction copy;
+ TestFundamentalObjectFinalizeFunction finalize;
+};
+
+GType test_fundamental_object_get_type (void);
+TestFundamentalObject* test_fundamental_object_ref (TestFundamentalObject *fundamental_object);
+void test_fundamental_object_unref (TestFundamentalObject *fundamental_object);
+
+#define TEST_VALUE_HOLDS_FUNDAMENTAL_OBJECT(value) (G_VALUE_HOLDS(value, TEST_TYPE_FUNDAMENTAL_OBJECT))
+
+void test_value_set_fundamental_object (GValue *value, TestFundamentalObject *fundamental_object);
+TestFundamentalObject* test_value_get_fundamental_object (const GValue *value);
+
+typedef struct _TestFundamentalSubObject TestFundamentalSubObject;
+typedef struct _TestFundamentalSubObjectClass TestFundamentalSubObjectClass;
+
+struct _TestFundamentalSubObject
+{
+ TestFundamentalObject fundamental_object;
+ char *data;
+};
+
+struct _TestFundamentalSubObjectClass {
+ TestFundamentalObjectClass fundamental_object_class;
+};
+
+GType test_fundamental_sub_object_get_type(void);
+
+TestFundamentalSubObject *
+test_fundamental_sub_object_new (const char *data);
+
/* callback */
typedef void (*TestSimpleCallback) (void);
typedef int (*TestCallback) (void);
diff --git a/girepository/gdump.c b/girepository/gdump.c
index 5cb10b04..328f0752 100644
--- a/girepository/gdump.c
+++ b/girepository/gdump.c
@@ -271,6 +271,56 @@ dump_enum_type (GType type, const char *symbol, GOutputStream *out)
}
static void
+dump_fundamental_type (GType type, const char *symbol, GOutputStream *out)
+{
+ guint n_interfaces;
+ guint i;
+ GType *interfaces;
+ GString *parent_str;
+ GType parent;
+ gboolean first = TRUE;
+
+
+ escaped_printf (out, " <fundamental name=\"%s\" get-type=\"%s\"",
+ g_type_name (type), symbol);
+
+ if (G_TYPE_IS_ABSTRACT (type))
+ escaped_printf (out, " abstract=\"1\"");
+
+ if (G_TYPE_IS_INSTANTIATABLE (type))
+ escaped_printf (out, " instantiatable=\"1\"");
+
+ parent = type;
+ parent_str = g_string_new ("");
+ do
+ {
+ parent = g_type_parent (parent);
+ if (first)
+ first = FALSE;
+ else
+ g_string_append_c (parent_str, ',');
+ if (!g_type_name (parent))
+ break;
+ g_string_append (parent_str, g_type_name (parent));
+ } while (parent != G_TYPE_INVALID);
+
+ if (parent_str->len > 0)
+ escaped_printf (out, " parents=\"%s\"", parent_str->str);
+ g_string_free (parent_str, TRUE);
+
+ goutput_write (out, ">\n");
+
+ interfaces = g_type_interfaces (type, &n_interfaces);
+ for (i = 0; i < n_interfaces; i++)
+ {
+ GType itype = interfaces[i];
+ escaped_printf (out, " <implements name=\"%s\"/>\n",
+ g_type_name (itype));
+ }
+ goutput_write (out, " </fundamental>\n");
+}
+
+static void
dump_type (GType type, const char *symbol, GOutputStream *out)
{
switch (g_type_fundamental (type))
@@ -294,10 +344,7 @@ dump_type (GType type, const char *symbol, GOutputStream *out)
/* GValue, etc. Just skip them. */
break;
default:
- /* Other fundamental types such as the once GStreamer and Clutter registers
- * are not yet interesting from an introspection perspective and should be
- * ignored
- */
+ dump_fundamental_type (type, symbol, out);
break;
}
}
diff --git a/girepository/giobjectinfo.c b/girepository/giobjectinfo.c
index ace8d5d4..bc2ddcd0 100644
--- a/girepository/giobjectinfo.c
+++ b/girepository/giobjectinfo.c
@@ -97,6 +97,29 @@ g_object_info_get_abstract (GIObjectInfo *info)
}
/**
+ * g_object_info_get_fundamental:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain if the object type is of a fundamental type which is not
+ * G_TYPE_OBJECT. This is mostly for supporting GstMiniObject.
+ *
+ * Returns: %TRUE if the object type is a fundamental type
+ */
+gboolean
+g_object_info_get_fundamental (GIObjectInfo *info)
+{
+ GIRealInfo *rinfo = (GIRealInfo *)info;
+ ObjectBlob *blob;
+
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), FALSE);
+
+ blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
+
+ return blob->fundamental != 0;
+}
+
+/**
* g_object_info_get_type_name:
* @info: a #GIObjectInfo
*
@@ -636,3 +659,229 @@ g_object_info_get_class_struct (GIObjectInfo *info)
return NULL;
}
+typedef const char* (*SymbolGetter) (GIObjectInfo *info);
+
+static void *
+_get_func(GIObjectInfo *info,
+ SymbolGetter getter)
+{
+ const char* symbol;
+ GSList *parents = NULL, *l;
+ GIObjectInfo *parent_info;
+
+ parent_info = info;
+ while (parent_info != NULL) {
+ parents = g_slist_prepend(parents, parent_info);
+ parent_info = g_object_info_get_parent(parent_info);
+ }
+
+ for (l = parents; l; l = l->next) {
+ GIObjectInfoRefFunction func;
+ parent_info = l->data;
+ symbol = getter(parent_info);
+ if (symbol == NULL)
+ continue;
+ if (g_typelib_symbol (((GIRealInfo *)parent_info)->typelib, symbol, (void**) &func)) {
+ g_slist_free(parents);
+ return func;
+ }
+ }
+
+ g_slist_free(parents);
+ return NULL;
+
+}
+
+/**
+ * g_object_info_get_ref_function:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain the symbol name of the function that should be called to ref this
+ * object type. It's mainly used fundamental types. The type signature for
+ * the symbol is %GIObjectInfoRefFunction, to fetch the function pointer
+ * see g_object_info_get_ref_function().
+ *
+ * Returns: the symbol or %NULL
+ */
+const char *
+g_object_info_get_ref_function (GIObjectInfo *info)
+{
+ GIRealInfo *rinfo = (GIRealInfo *)info;
+ ObjectBlob *blob;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
+
+ if (blob->ref_func)
+ return g_typelib_get_string (rinfo->typelib, blob->ref_func);
+
+ return NULL;
+}
+
+/**
+ * g_object_info_get_ref_function_pointer:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain a pointer to a function which can be used to
+ * increase the reference count an instance of this object type.
+ * This takes derivation into account and will reversely traverse
+ * the base classes of this type, starting at the top type.
+ *
+ * Returns: the function pointer or %NULL
+ */
+GIObjectInfoRefFunction
+g_object_info_get_ref_function_pointer (GIObjectInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ return (GIObjectInfoRefFunction)_get_func(info, (SymbolGetter)g_object_info_get_ref_function);
+}
+
+/**
+ * g_object_info_get_unref_function:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain the symbol name of the function that should be called to unref this
+ * object type. It's mainly used fundamental types. The type signature for
+ * the symbol is %GIObjectInfoUnrefFunction, to fetch the function pointer
+ * see g_object_info_get_unref_function().
+ *
+ * Returns: the symbol or %NULL
+ */
+const char *
+g_object_info_get_unref_function (GIObjectInfo *info)
+{
+ GIRealInfo *rinfo = (GIRealInfo *)info;
+ ObjectBlob *blob;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
+
+ if (blob->unref_func)
+ return g_typelib_get_string (rinfo->typelib, blob->unref_func);
+
+ return NULL;
+}
+
+/**
+ * g_object_info_get_unref_function_pointer:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain a pointer to a function which can be used to
+ * decrease the reference count an instance of this object type.
+ * This takes derivation into account and will reversely traverse
+ * the base classes of this type, starting at the top type.
+ *
+ * Returns: the function pointer or %NULL
+ */
+GIObjectInfoUnrefFunction
+g_object_info_get_unref_function_pointer (GIObjectInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ return (GIObjectInfoUnrefFunction)_get_func(info, (SymbolGetter)g_object_info_get_unref_function);
+}
+
+/**
+ * g_object_info_get_set_value_function:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain the symbol name of the function that should be called to convert
+ * set a GValue giving an object instance pointer of this object type.
+ * I's mainly used fundamental types. The type signature for the symbol
+ * is %GIObjectInfoSetValueFunction, to fetch the function pointer
+ * see g_object_info_get_set_value_function().
+ *
+ * Returns: the symbol or %NULL
+ */
+const char *
+g_object_info_get_set_value_function (GIObjectInfo *info)
+{
+ GIRealInfo *rinfo = (GIRealInfo *)info;
+ ObjectBlob *blob;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
+
+ if (blob->set_value_func)
+ return g_typelib_get_string (rinfo->typelib, blob->set_value_func);
+
+ return NULL;
+}
+
+/**
+ * g_object_info_get_set_value_function_pointer:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain a pointer to a function which can be used to
+ * set a GValue given an instance of this object type.
+ * This takes derivation into account and will reversely traverse
+ * the base classes of this type, starting at the top type.
+ *
+ * Returns: the function pointer or %NULL
+ */
+GIObjectInfoSetValueFunction
+g_object_info_get_set_value_function_pointer (GIObjectInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ return (GIObjectInfoSetValueFunction)_get_func(info, (SymbolGetter)g_object_info_get_set_value_function);
+}
+
+/**
+ * g_object_info_get_get_value_function:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain the symbol name of the function that should be called to convert
+ * an object instance pointer of this object type to a GValue.
+ * I's mainly used fundamental types. The type signature for the symbol
+ * is %GIObjectInfoGetValueFunction, to fetch the function pointer
+ * see g_object_info_get_get_value_function().
+ *
+ * Returns: the symbol or %NULL
+ */
+const char *
+g_object_info_get_get_value_function (GIObjectInfo *info)
+{
+ GIRealInfo *rinfo = (GIRealInfo *)info;
+ ObjectBlob *blob;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
+
+ if (blob->get_value_func)
+ return g_typelib_get_string (rinfo->typelib, blob->get_value_func);
+
+ return NULL;
+}
+
+/**
+ * g_object_info_get_get_value_function_pointer:
+ * @info: a #GIObjectInfo
+ *
+ * Obtain a pointer to a function which can be used to
+ * extract an instance of this object type out of a GValue.
+ * This takes derivation into account and will reversely traverse
+ * the base classes of this type, starting at the top type.
+ *
+ * Returns: the function pointer or %NULL
+ */
+GIObjectInfoGetValueFunction
+g_object_info_get_get_value_function_pointer (GIObjectInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
+
+ return (GIObjectInfoGetValueFunction)_get_func(info, (SymbolGetter)g_object_info_get_get_value_function);
+}
diff --git a/girepository/giobjectinfo.h b/girepository/giobjectinfo.h
index 27ec7141..630def61 100644
--- a/girepository/giobjectinfo.h
+++ b/girepository/giobjectinfo.h
@@ -30,12 +30,52 @@
G_BEGIN_DECLS
+/**
+ * GIObjectInfoRefFunction:
+ * @object: object instance pointer
+ *
+ * Increases the reference count of an object instance.
+ *
+ * Returns: the object instance
+ */
+typedef void * (*GIObjectInfoRefFunction) (void *object);
+
+/**
+ * GIObjectInfoUnrefFunction:
+ * @object: object instance pointer
+ *
+ * Decreases the reference count of an object instance.
+ *
+ */
+typedef void (*GIObjectInfoUnrefFunction) (void *object);
+
+/**
+ * GIObjectInfoSetValueFunction:
+ * @value: a #GValue
+ * @object: object instance pointer
+ *
+ * Update @value and attach the object instance pointer @object to it.
+ *
+ */
+typedef void (*GIObjectInfoSetValueFunction) (GValue *value, void *object);
+
+/**
+ * GIObjectInfoGetValueFunction:
+ * @value: a #GValue
+ *
+ * Extract an object instance out of @value
+ *
+ * Returns: the object instance
+ */
+typedef void * (*GIObjectInfoGetValueFunction) (const GValue *value);
+
#define GI_IS_OBJECT_INFO(info) \
(g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_OBJECT)
const gchar * g_object_info_get_type_name (GIObjectInfo *info);
const gchar * g_object_info_get_type_init (GIObjectInfo *info);
gboolean g_object_info_get_abstract (GIObjectInfo *info);
+gboolean g_object_info_get_fundamental (GIObjectInfo *info);
GIObjectInfo * g_object_info_get_parent (GIObjectInfo *info);
gint g_object_info_get_n_interfaces (GIObjectInfo *info);
GIInterfaceInfo * g_object_info_get_interface (GIObjectInfo *info,
@@ -64,6 +104,18 @@ GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info,
gint n);
GIStructInfo * g_object_info_get_class_struct (GIObjectInfo *info);
+const char * g_object_info_get_ref_function (GIObjectInfo *info);
+GIObjectInfoRefFunction g_object_info_get_ref_function_pointer (GIObjectInfo *info);
+
+const char * g_object_info_get_unref_function (GIObjectInfo *info);
+GIObjectInfoUnrefFunction g_object_info_get_unref_function_pointer (GIObjectInfo *info);
+
+const char * g_object_info_get_set_value_function (GIObjectInfo *info);
+GIObjectInfoSetValueFunction g_object_info_get_set_value_function_pointer (GIObjectInfo *info);
+
+const char * g_object_info_get_get_value_function (GIObjectInfo *info);
+GIObjectInfoGetValueFunction g_object_info_get_get_value_function_pointer (GIObjectInfo *info);
+
G_END_DECLS
diff --git a/girepository/giregisteredtypeinfo.h b/girepository/giregisteredtypeinfo.h
index f3c20fdd..76a1ee22 100644
--- a/girepository/giregisteredtypeinfo.h
+++ b/girepository/giregisteredtypeinfo.h
@@ -38,7 +38,8 @@ G_BEGIN_DECLS
(g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_INTERFACE) || \
(g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_OBJECT) || \
(g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_STRUCT) || \
- (g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_UNION))
+ (g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_UNION) || \
+ (g_base_info_get_type((GIBaseInfo*)info) == GI_INFO_TYPE_BOXED))
const gchar * g_registered_type_info_get_type_name (GIRegisteredTypeInfo *info);
const gchar * g_registered_type_info_get_type_init (GIRegisteredTypeInfo *info);
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 576ac100..af24161d 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -298,6 +298,10 @@ g_ir_node_free (GIrNode *node)
g_free (node->name);
g_free (iface->gtype_name);
g_free (iface->gtype_init);
+ g_free (iface->ref_func);
+ g_free (iface->unref_func);
+ g_free (iface->set_value_func);
+ g_free (iface->get_value_func);
g_free (iface->glib_type_struct);
@@ -692,6 +696,14 @@ g_ir_node_get_full_size_internal (GIrNode *parent,
size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
if (iface->gtype_init)
size += ALIGN_VALUE (strlen (iface->gtype_init) + 1, 4);
+ if (iface->ref_func)
+ size += ALIGN_VALUE (strlen (iface->ref_func) + 1, 4);
+ if (iface->unref_func)
+ size += ALIGN_VALUE (strlen (iface->unref_func) + 1, 4);
+ if (iface->set_value_func)
+ size += ALIGN_VALUE (strlen (iface->set_value_func) + 1, 4);
+ if (iface->get_value_func)
+ size += ALIGN_VALUE (strlen (iface->get_value_func) + 1, 4);
size += 2 * (n + (n % 2));
for (l = iface->members; l; l = l->next)
@@ -2094,11 +2106,20 @@ g_ir_node_build_typelib (GIrNode *node,
blob->blob_type = BLOB_TYPE_OBJECT;
blob->abstract = object->abstract;
+ blob->fundamental = object->fundamental;
blob->deprecated = object->deprecated;
blob->reserved = 0;
blob->name = write_string (node->name, strings, data, offset2);
blob->gtype_name = write_string (object->gtype_name, strings, data, offset2);
blob->gtype_init = write_string (object->gtype_init, strings, data, offset2);
+ if (object->ref_func)
+ blob->ref_func = write_string (object->ref_func, strings, data, offset2);
+ if (object->unref_func)
+ blob->unref_func = write_string (object->unref_func, strings, data, offset2);
+ if (object->set_value_func)
+ blob->set_value_func = write_string (object->set_value_func, strings, data, offset2);
+ if (object->get_value_func)
+ blob->get_value_func = write_string (object->get_value_func, strings, data, offset2);
if (object->parent)
blob->parent = find_entry (module, modules, object->parent);
else
diff --git a/girepository/girnode.h b/girepository/girnode.h
index bd9acd06..dcd8fa49 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -244,10 +244,16 @@ struct _GIrNodeInterface
gboolean abstract;
gboolean deprecated;
+ gboolean fundamental;
gchar *gtype_name;
gchar *gtype_init;
+ gchar *ref_func;
+ gchar *unref_func;
+ gchar *set_value_func;
+ gchar *get_value_func;
+
gchar *parent;
gchar *glib_type_struct;
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 678edcc3..7796bea2 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -1640,6 +1640,11 @@ start_class (GMarkupParseContext *context,
const gchar *typeinit;
const gchar *deprecated;
const gchar *abstract;
+ const gchar *fundamental;
+ const gchar *ref_func;
+ const gchar *unref_func;
+ const gchar *set_value_func;
+ const gchar *get_value_func;
GIrNodeInterface *iface;
if (!(strcmp (element_name, "class") == 0 &&
@@ -1656,6 +1661,11 @@ start_class (GMarkupParseContext *context,
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
abstract = find_attribute ("abstract", attribute_names, attribute_values);
+ fundamental = find_attribute ("glib:fundamental", attribute_names, attribute_values);
+ ref_func = find_attribute ("glib:ref-func", attribute_names, attribute_values);
+ unref_func = find_attribute ("glib:unref-func", attribute_names, attribute_values);
+ set_value_func = find_attribute ("glib:set-value-func", attribute_names, attribute_values);
+ get_value_func = find_attribute ("glib:get-value-func", attribute_names, attribute_values);
if (name == NULL)
{
@@ -1686,6 +1696,15 @@ start_class (GMarkupParseContext *context,
iface->abstract = abstract && strcmp (abstract, "1") == 0;
+ if (ref_func)
+ iface->ref_func = g_strdup (ref_func);
+ if (unref_func)
+ iface->unref_func = g_strdup (unref_func);
+ if (set_value_func)
+ iface->set_value_func = g_strdup (set_value_func);
+ if (get_value_func)
+ iface->get_value_func = g_strdup (get_value_func);
+
push_node (ctx, (GIrNode *) iface);
ctx->current_module->entries =
g_list_append (ctx->current_module->entries, iface);
diff --git a/girepository/girwriter.c b/girepository/girwriter.c
index 19862b0d..56d61b23 100644
--- a/girepository/girwriter.c
+++ b/girepository/girwriter.c
@@ -999,8 +999,10 @@ write_object_info (const gchar *namespace,
const gchar *name;
const gchar *type_name;
const gchar *type_init;
+ const gchar *func;
gboolean deprecated;
gboolean is_abstract;
+ gboolean is_fundamental;
GIObjectInfo *pnode;
GIStructInfo *class_struct;
gint i;
@@ -1008,6 +1010,7 @@ write_object_info (const gchar *namespace,
name = g_base_info_get_name ((GIBaseInfo *)info);
deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
is_abstract = g_object_info_get_abstract (info);
+ is_fundamental = g_object_info_get_fundamental (info);
type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
@@ -1033,6 +1036,25 @@ write_object_info (const gchar *namespace,
xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
+ if (is_fundamental)
+ xml_printf (file, " glib:fundamental=\"1\"");
+
+ func = g_object_info_get_unref_function (info);
+ if (func)
+ xml_printf (file, " glib:unref-function=\"%s\"", func);
+
+ func = g_object_info_get_ref_function (info);
+ if (func)
+ xml_printf (file, " glib:ref-function=\"%s\"", func);
+
+ func = g_object_info_get_set_value_function (info);
+ if (func)
+ xml_printf (file, " glib:set-value-function=\"%s\"", func);
+
+ func = g_object_info_get_get_value_function (info);
+ if (func)
+ xml_printf (file, " glib:get-value-function=\"%s\"", func);
+
if (deprecated)
xml_printf (file, " deprecated=\"1\"");
diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h
index d4577acc..981f7b48 100644
--- a/girepository/gitypelib-internal.h
+++ b/girepository/gitypelib-internal.h
@@ -72,6 +72,11 @@ G_BEGIN_DECLS
/*
TYPELIB HISTORY
-----
+
+Version 1.1
+- Add ref/unref/set-value/get-value functions to Object, to be able
+ to support instantiatable fundamental types which are not GObject based.
+
Version 1.0
- Rename class_struct to gtype_struct, add to interfaces
@@ -918,6 +923,8 @@ typedef struct {
/**
* ObjectBlob:
* @blob_type: #BLOB_TYPE_OBJECT
+ * @fundamental: this object is not a GObject derived type, instead it's
+ * an additional fundamental type.
* @gtype_name: String name of the associated #GType
* @gtype_init: String naming the symbol which gets the runtime #GType
* @parent: The directory index of the parent type. This is only set for
@@ -938,12 +945,21 @@ typedef struct {
* @signals: Describes the signals.
* @vfuncs: Describes the virtual functions.
* @constants: Describes the constants.
+ * @ref_func: String pointing to a function which can be called to increase
+ * the reference count for an instance of this object type.
+ * @unref_func: String pointing to a function which can be called to decrease
+ * the reference count for an instance of this object type.
+ * @set_value_func: String pointing to a function which can be called to
+ * convert a pointer of this object to a GValue
+ * @get_value_func: String pointing to a function which can be called to
+ * convert extract a pointer to this object from a GValue
*/
typedef struct {
guint16 blob_type; /* 7 */
guint16 deprecated : 1;
guint16 abstract : 1;
- guint16 reserved :14;
+ guint16 fundamental : 1;
+ guint16 reserved :13;
guint32 name;
guint32 gtype_name;
@@ -961,6 +977,11 @@ typedef struct {
guint16 n_constants;
guint16 reserved2;
+ guint32 ref_func;
+ guint32 unref_func;
+ guint32 set_value_func;
+ guint32 get_value_func;
+
guint32 reserved3;
guint32 reserved4;
diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c
index 6aa3077c..74aa7edd 100644
--- a/girepository/gitypelib.c
+++ b/girepository/gitypelib.c
@@ -183,7 +183,7 @@ g_typelib_check_sanity (void)
CHECK_SIZE (PropertyBlob, 16);
CHECK_SIZE (SignalBlob, 16);
CHECK_SIZE (VFuncBlob, 20);
- CHECK_SIZE (ObjectBlob, 44);
+ CHECK_SIZE (ObjectBlob, 60);
CHECK_SIZE (InterfaceBlob, 40);
CHECK_SIZE (ConstantBlob, 24);
CHECK_SIZE (AttributeBlob, 12);
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 03ffb546..c642d56e 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -52,6 +52,10 @@ TAG_ATTRIBUTES = 'attributes'
TAG_RENAME_TO = 'rename to'
TAG_TYPE = 'type'
TAG_TRANSFER = 'transfer'
+TAG_UNREF_FUNC = 'unref func'
+TAG_REF_FUNC = 'ref func'
+TAG_SET_VALUE_FUNC = 'set value func'
+TAG_GET_VALUE_FUNC = 'get value func'
# Options - annotations for parameters and return values
OPT_ALLOW_NONE = 'allow-none'
@@ -361,6 +365,7 @@ class AnnotationApplier(object):
self._parse_fields(class_, class_.fields)
if block:
class_.doc = block.comment
+ self._parse_type_instance_tags(class_, block)
def _parse_interface(self, interface):
block = self._blocks.get(interface.type_name)
@@ -911,6 +916,16 @@ class AnnotationApplier(object):
if OPT_FOREIGN in block.options:
node.foreign = True
+ def _parse_type_instance_tags(self, node, block):
+ tag = self._get_tag(block, TAG_UNREF_FUNC)
+ node.unref_func = tag.value if tag else None
+ tag = self._get_tag(block, TAG_REF_FUNC)
+ node.ref_func = tag.value if tag else None
+ tag = self._get_tag(block, TAG_SET_VALUE_FUNC)
+ node.set_value_func = tag.value if tag else None
+ tag = self._get_tag(block, TAG_GET_VALUE_FUNC)
+ node.get_value_func = tag.value if tag else None
+
def _parse_rename_to_func(self, node, block):
rename_to_tag = self._get_tag(block, TAG_RENAME_TO)
if rename_to_tag is None:
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 5e29d067..2e0a6cdc 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -348,6 +348,17 @@ and/or use gtk-doc annotations. ''')
attrs.append(('glib:get-type', node.get_type))
if node.glib_type_struct:
attrs.append(('glib:type-struct', node.glib_type_struct.name))
+ if isinstance(node, GLibObject):
+ if node.fundamental:
+ attrs.append(('glib:fundamental', '1'))
+ if node.ref_func:
+ attrs.append(('glib:ref-func', node.ref_func))
+ if node.unref_func:
+ attrs.append(('glib:unref-func', node.unref_func))
+ if node.set_value_func:
+ attrs.append(('glib:set-value-func', node.set_value_func))
+ if node.get_value_func:
+ attrs.append(('glib:get-value-func', node.get_value_func))
with self.tagcontext(tag_name, attrs):
self._write_generic(node)
if isinstance(node, GLibObject):
diff --git a/giscanner/glibast.py b/giscanner/glibast.py
index fb1ef208..c7129883 100644
--- a/giscanner/glibast.py
+++ b/giscanner/glibast.py
@@ -120,6 +120,11 @@ class GLibObject(Class):
Class.__init__(self, name, parent, is_abstract)
self.type_name = type_name
self.get_type = get_type
+ self.fundamental = False
+ self.unref_func = None
+ self.ref_func = None
+ self.set_value_func = None
+ self.get_value_func = None
self.signals = []
self.ctype = ctype or type_name
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 3b088bcb..1178c5fa 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -689,6 +689,8 @@ class GLibTransformer(object):
self._introspect_interface(xmlnode)
elif xmlnode.tag == 'boxed':
self._introspect_boxed(xmlnode)
+ elif xmlnode.tag == 'fundamental':
+ self._introspect_fundamental(xmlnode)
else:
raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
@@ -808,6 +810,36 @@ class GLibTransformer(object):
node.signals.append(signal)
node.signals = sorted(node.signals)
+ def _introspect_fundamental(self, xmlnode):
+ # We only care about types that can be instantiatable, other
+ # fundamental types such as the Clutter.Fixed/CoglFixed registers
+ # are not yet interesting from an introspection perspective and
+ # are ignored
+ if not xmlnode.attrib.get('instantiatable', False):
+ return
+
+ type_name = xmlnode.attrib['name']
+
+ # Get a list of parents here; some of them may be hidden, and what
+ # we really want to do is use the most-derived one that we know of.
+ if 'parents' in xmlnode.attrib:
+ parent_type_names = xmlnode.attrib['parents'].split(',')
+ parent_gitype = self._resolve_gtypename_chain(parent_type_names)
+ else:
+ parent_gitype = None
+ is_abstract = bool(xmlnode.attrib.get('abstract', False))
+ node = GLibObject(
+ self._transformer.remove_prefix(type_name),
+ parent_gitype,
+ type_name,
+ xmlnode.attrib['get-type'], is_abstract)
+ node.fundamental = True
+ self._introspect_implemented_interfaces(node, xmlnode)
+
+ self._add_record_fields(node)
+ self._add_attribute(node, replace=True)
+ self._register_internal_type(type_name, node)
+
def _add_record_fields(self, node):
# add record fields
record = self._get_attribute(node.name)