GObject binary typelib for introspection
-----------------------------------------
-Version 0.8
+Version 0.9
+
+Changes since 0.8:
+- Add class struct concept to ObjectBlob
+- Add is_class_struct bit to StructBlob
Changes since 0.7:
- Add dependencies
guint deprecated : 1;
guint unregistered : 1;
guint alignment : 6;
- guint reserved : 8;
+ guint is_class_struct : 1
+ guint reserved : 7;
guint32 name;
GTypeBlob gtype;
alignment:
The byte boundary that the struct is aligned to in memory
+
+is_class_struct:
+ Whether this structure is the "class structure" for a GObject
size: The size of the struct in bytes.
values: Describes the enum values.
-ObjectBlob (32 + x bytes)
+ObjectBlob (36 + x bytes)
struct ObjectBlob
{
GTypeBlob gtype;
guint16 parent;
+ guint16 class_struct;
guint16 n_interfaces;
guint16 n_fields;
return blob->alignment;
}
+/**
+ * g_struct_info_is_class_struct:
+ * @info: GIStructInfo
+ *
+ * Return true if this structure represents the "class structure" for some
+ * GObject. This function is mainly useful to hide this kind of structure
+ * from public APIs.
+ *
+ */
+gboolean
+g_struct_info_is_class_struct (GIStructInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ StructBlob *blob = (StructBlob *)&base->typelib->data[base->offset];
+
+ return blob->is_class_struct;
+}
+
gint
g_enum_info_get_n_values (GIEnumInfo *info)
{
base->typelib, offset);
}
+/**
+ * g_object_info_get_class_struct:
+ * @info: A #GIObjectInfo to query
+ *
+ * Every GObject has two structures; an instance structure and a class
+ * structure. This function returns the metadata for the class structure.
+ */
+GIStructInfo *
+g_object_info_get_class_struct (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->typelib->data[base->offset];
+
+ if (blob->class_struct)
+ return (GIStructInfo *) g_info_from_entry (base->repository,
+ base->typelib, blob->class_struct);
+ else
+ return NULL;
+}
/* GIInterfaceInfo functions */
gint
const gchar *name);
gsize g_struct_info_get_size (GIStructInfo *info);
gsize g_struct_info_get_alignment (GIStructInfo *info);
+gboolean g_struct_info_is_class_struct (GIStructInfo *info);
/* GIRegisteredTypeInfo */
gint g_object_info_get_n_constants (GIObjectInfo *info);
GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info,
gint n);
+GIStructInfo * g_object_info_get_class_struct (GIObjectInfo *info);
/* GIInterfaceInfo */
header->signature_blob_size = 8;
header->enum_blob_size = 20;
header->struct_blob_size = 24;
- header->object_blob_size = 32;
+ header->object_blob_size = sizeof(ObjectBlob);
header->interface_blob_size = 28;
header->union_blob_size = 32;
g_free (node->name);
g_free (iface->gtype_name);
g_free (iface->gtype_init);
-
+
+ g_free (iface->class_struct);
g_free (iface->parent);
for (l = iface->interfaces; l; l = l->next)
GIrNodeInterface *iface = (GIrNodeInterface *)node;
n = g_list_length (iface->interfaces);
- size = 32 + 2 * (n + (n % 2));
+ size = sizeof(ObjectBlob) + 2 * (n + (n % 2));
for (l = iface->members; l; l = l->next)
size += g_ir_node_get_size ((GIrNode *)l->data);
GIrNodeInterface *iface = (GIrNodeInterface *)node;
n = g_list_length (iface->interfaces);
- size = 32;
+ size = sizeof(ObjectBlob);
if (iface->parent)
size += ALIGN_VALUE (strlen (iface->parent) + 1, 4);
+ if (iface->class_struct)
+ size += ALIGN_VALUE (strlen (iface->class_struct) + 1, 4);
size += ALIGN_VALUE (strlen (node->name) + 1, 4);
size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
if (iface->gtype_init)
blob->blob_type = BLOB_TYPE_STRUCT;
blob->deprecated = struct_->deprecated;
+ blob->is_class_struct = struct_->is_gclass_struct;
blob->reserved = 0;
blob->name = write_string (node->name, strings, data, offset2);
blob->alignment = struct_->alignment;
blob->parent = find_entry (module, modules, object->parent);
else
blob->parent = 0;
+ if (object->class_struct)
+ blob->class_struct = find_entry (module, modules, object->class_struct);
+ else
+ blob->class_struct = 0;
blob->n_interfaces = 0;
blob->n_fields = 0;
blob->n_vfuncs = 0;
blob->n_constants = 0;
- *offset += 32;
+ *offset += sizeof(ObjectBlob);
for (l = object->interfaces; l; l = l->next)
{
blob->n_interfaces++;
gchar *gtype_init;
gchar *parent;
+ gchar *class_struct; /* Only applies to classes */
GList *interfaces;
GList *prerequisites;
gboolean deprecated;
gboolean disguised;
+ gboolean is_gclass_struct;
gchar *gtype_name;
gchar *gtype_init;
{
const gchar *name;
const gchar *parent;
+ const gchar *class_struct;
const gchar *typename;
const gchar *typeinit;
const gchar *deprecated;
name = find_attribute ("name", attribute_names, attribute_values);
parent = find_attribute ("parent", attribute_names, attribute_values);
+ class_struct = find_attribute ("glib:class-struct", attribute_names, attribute_values);
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
iface->gtype_name = g_strdup (typename);
iface->gtype_init = g_strdup (typeinit);
iface->parent = g_strdup (parent);
+ iface->class_struct = g_strdup (class_struct);
if (deprecated)
iface->deprecated = TRUE;
else
const gchar *disguised;
const gchar *gtype_name;
const gchar *gtype_init;
+ const gchar *gclass_struct;
GIrNodeStruct *struct_;
name = find_attribute ("name", attribute_names, attribute_values);
disguised = find_attribute ("disguised", attribute_names, attribute_values);
gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
+ gclass_struct = find_attribute ("glib:is-class-struct-for", attribute_names, attribute_values);
if (name == NULL && ctx->node_stack == NULL)
{
if (disguised && strcmp (disguised, "1") == 0)
struct_->disguised = TRUE;
+
+ struct_->is_gclass_struct = gclass_struct != NULL;
struct_->gtype_name = g_strdup (gtype_name);
struct_->gtype_init = g_strdup (gtype_init);
CHECK_SIZE (PropertyBlob, 12);
CHECK_SIZE (SignalBlob, 12);
CHECK_SIZE (VFuncBlob, 16);
- CHECK_SIZE (ObjectBlob, 32);
+ CHECK_SIZE (ObjectBlob, 36);
CHECK_SIZE (InterfaceBlob, 28);
CHECK_SIZE (ConstantBlob, 20);
CHECK_SIZE (AnnotationBlob, 12);
"Typelib size mismatch");
return FALSE;
}
+
+ /* This is a sanity check for a specific typelib; it
+ * prevents us from loading an incompatible typelib. It's OK to change
+ * these hardcoded constants to sizeof() as you see fit.
+ *
+ * We want to keep the hardcoded checks in g_typelib_check_sanity to
+ * protect against inadvertent or buggy changes to the typelib format
+ * itself.
+ */
if (header->entry_blob_size != 12 ||
header->function_blob_size != 20 ||
header->signature_blob_size != 8 ||
header->enum_blob_size != 20 ||
header->struct_blob_size != 24 ||
- header->object_blob_size != 32 ||
+ header->object_blob_size != sizeof(ObjectBlob) ||
header->interface_blob_size != 28 ||
header->union_blob_size != 32)
{
{
DirEntry *entry;
- entry = g_typelib_get_dir_entry (typelib, blob->parent);
+ entry = get_dir_entry_checked (typelib, blob->parent, error);
+ if (!entry)
+ return FALSE;
if (entry->blob_type != BLOB_TYPE_OBJECT &&
(entry->local || entry->blob_type != 0))
{
}
}
+ if (blob->class_struct != 0)
+ {
+ DirEntry *entry;
+
+ entry = get_dir_entry_checked (typelib, blob->class_struct, error);
+ if (!entry)
+ return FALSE;
+ if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Class struct invalid type or not local");
+ return FALSE;
+ }
+ }
+
if (typelib->len < offset + sizeof (ObjectBlob) +
(blob->n_interfaces + blob->n_interfaces % 2) * 2 +
blob->n_fields * sizeof (FieldBlob) +
return FALSE;
}
- entry = g_typelib_get_dir_entry (typelib, iface);
+ entry = get_dir_entry_checked (typelib, iface, error);
+ if (!entry)
+ return FALSE;
if (entry->blob_type != BLOB_TYPE_INTERFACE &&
(entry->local || entry->blob_type != 0))
guint16 deprecated : 1;
guint16 unregistered : 1;
- guint16 alignment : 6;
- guint16 reserved : 8;
+ guint16 is_class_struct : 1;
+ guint16 alignment : 6;
+ guint16 reserved : 7;
guint32 name;
guint32 gtype_init;
guint16 parent;
+ guint16 class_struct;
+ guint16 reserved2;
guint16 n_interfaces;
guint16 n_fields;
self.doc = None
self.constructors = []
self.methods = []
+ # If true, this record defines the FooClass C structure
+ # for some Foo GObject
+ self.is_gobject_struct_for = False
# BW compat, remove
Struct = Record
Node.__init__(self, name)
self.ctype = name
self.parent = parent
+ self.class_struct = None
self.is_abstract = is_abstract
self.methods = []
self.static_methods = []
attrs.append(('glib:type-name', node.type_name))
if node.get_type:
attrs.append(('glib:get-type', node.get_type))
+ if isinstance(node, GLibObject):
+ if node.class_struct:
+ attrs.append(('glib:class-struct', node.class_struct.name))
with self.tagcontext(tag_name, attrs):
if isinstance(node, GLibObject):
for iface in node.interfaces:
return [('glib:type-name', boxed.type_name),
('glib:get-type', boxed.get_type)]
- def _write_record(self, record):
- attrs = []
+ def _write_record(self, record, extra_attrs=[]):
+ attrs = list(extra_attrs)
if record.name is not None:
attrs.append(('name', record.name))
if record.symbol is not None: # the record might be anonymous
attrs.append(('c:type', record.symbol))
if record.disguised:
attrs.append(('disguised', '1'))
+ if record.is_gobject_struct_for:
+ attrs.append(('glib:is-class-struct-for',
+ record.is_gobject_struct_for))
if record.doc:
attrs.append(('doc', record.doc))
self._append_version(record, attrs)
if name == maybe_class.name:
return
- if self._arg_is_failed(maybe_class):
- print "WARNING: deleting no-type %r" % (maybe_class.name, )
- del self._names.names[maybe_class.name]
+ class_struct = maybe_class
+ if self._arg_is_failed(class_struct):
+ print "WARNING: deleting no-type %r" % (class_struct.name, )
+ del self._names.names[class_struct.name]
+ return
+
+ pair_class = self._get_attribute(name)
+ if (not pair_class or
+ not isinstance(pair_class, (GLibObject, GLibInterface))):
return
# Object class fields are assumed to be read-only
for field in maybe_class.fields:
if isinstance(field, Field):
field.writable = False
-
- name = self._resolve_type_name(name)
- resolved = self._transformer.remove_prefix(name)
- pair_class = self._get_attribute(resolved)
- if pair_class and isinstance(pair_class, GLibInterface):
+ if isinstance(pair_class, GLibInterface):
for field in maybe_class.fields[1:]:
pair_class.fields.append(field)
return
- name = self._transformer.remove_prefix(maybe_class.name)
- pair_class = self._get_attribute(name)
- if pair_class and isinstance(pair_class,
- (GLibObject, GLibInterface)):
-
- del self._names.names[maybe_class.name]
+ elif isinstance(pair_class, GLibObject):
+ pair_class.class_struct = class_struct
+ class_struct.is_gobject_struct_for = name
# Introspection
c:type="BarBaz"
parent="GObject.Object"
glib:type-name="BarBaz"
- glib:get-type="bar_baz_get_type">
+ glib:get-type="bar_baz_get_type"
+ glib:class-struct="BazClass">
<field name="parent_instance">
<type name="GObject.Object" c:type="GObject"/>
</field>
</class>
- <record name="BazClass" c:type="BarBazClass">
+ <record name="BazClass"
+ c:type="BarBazClass"
+ glib:is-class-struct-for="Baz">
<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
<namespace name="BarApp" version="1.0" shared-library="">
- <class name="Baz" parent="GObject.Object" glib:type-name="BarBaz" glib:get-type="bar_baz_get_type">
+ <class name="Baz" parent="GObject.Object" glib:class-struct="BazClass" glib:type-name="BarBaz" glib:get-type="bar_baz_get_type">
<field name="parent_instance">
<type name="GObject.Object"/>
</field>
</class>
- <record name="BazClass">
+ <record name="BazClass" glib:is-class-struct="1">
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
doc="This is an object used to test annotations."
parent="GObject.Object"
glib:type-name="AnnotationObject"
- glib:get-type="annotation_object_get_type">
+ glib:get-type="annotation_object_get_type"
+ glib:class-struct="ObjectClass">
<method name="method" c:identifier="annotation_object_method">
<return-value transfer-ownership="none">
<type name="int" c:type="gint"/>
</parameters>
</glib:signal>
</class>
- <record name="ObjectClass" c:type="AnnotationObjectClass">
+ <record name="ObjectClass"
+ c:type="AnnotationObjectClass"
+ glib:is-class-struct-for="Object">
<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
</parameter>
</parameters>
</callback>
- <class name="Object" parent="GObject.Object" glib:type-name="AnnotationObject" glib:get-type="annotation_object_get_type">
+ <class name="Object" parent="GObject.Object" glib:class-struct="ObjectClass" glib:type-name="AnnotationObject" glib:get-type="annotation_object_get_type">
<field name="parent_instance">
<type name="GObject.Object"/>
</field>
</type>
</return-value>
</method>
+ <method name="with_voidp" c:identifier="annotation_object_with_voidp">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="data" transfer-ownership="none">
+ <type name="any"/>
+ </parameter>
+ </parameters>
+ </method>
<method name="get_objects" c:identifier="annotation_object_get_objects">
<return-value transfer-ownership="container">
<type name="GLib.SList">
</parameters>
</glib:signal>
</class>
- <record name="ObjectClass">
+ <record name="ObjectClass" glib:is-class-struct="1">
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
parent="GObject.Object"
abstract="1"
glib:type-name="TestDrawable"
- glib:get-type="test_drawable_get_type">
+ glib:get-type="test_drawable_get_type"
+ glib:class-struct="TestDrawableClass">
<method name="do_foo" c:identifier="test_drawable_do_foo">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
<type name="GObject.Object" c:type="GObject"/>
</field>
</class>
- <record name="TestDrawableClass" c:type="TestDrawableClass">
+ <record name="TestDrawableClass"
+ c:type="TestDrawableClass"
+ glib:is-class-struct-for="TestDrawable">
<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
</record>
<record name="TestPixmapObjectClass" c:type="_TestPixmapObjectClass">
- <field name="parent_class">
+ <field name="parent_class" writable="1">
<type name="TestDrawableClass" c:type="TestDrawableClass"/>
</field>
</record>
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
<namespace name="drawable" version="1.0" shared-library="drawable">
- <class name="TestDrawable" parent="GObject.Object" abstract="1" glib:type-name="TestDrawable" glib:get-type="test_drawable_get_type">
+ <class name="TestDrawable" parent="GObject.Object" glib:class-struct="TestDrawableClass" abstract="1" glib:type-name="TestDrawable" glib:get-type="test_drawable_get_type">
<field name="parent_instance">
<type name="GObject.Object"/>
</field>
</parameters>
</method>
</class>
- <record name="TestDrawableClass">
+ <record name="TestDrawableClass" glib:is-class-struct="1">
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
</record>
<record name="TestPixmapObjectClass">
- <field name="parent_class">
+ <field name="parent_class" writable="1">
<type name="TestDrawableClass"/>
</field>
</record>
c:type="FooObject"
parent="GObject.Object"
glib:type-name="FooObject"
- glib:get-type="foo_object_get_type">
+ glib:get-type="foo_object_get_type"
+ glib:class-struct="ObjectClass">
<implements name="Interface"/>
<constructor name="new" c:identifier="foo_object_new">
<return-value transfer-ownership="full">
</parameters>
</glib:signal>
</class>
- <record name="ObjectClass" c:type="FooObjectClass">
+ <record name="ObjectClass"
+ c:type="FooObjectClass"
+ glib:is-class-struct-for="Object">
<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
parent="Object"
abstract="1"
glib:type-name="FooSubobject"
- glib:get-type="foo_subobject_get_type">
+ glib:get-type="foo_subobject_get_type"
+ glib:class-struct="SubobjectClass">
<implements name="Interface"/>
<constructor name="new" c:identifier="foo_subobject_new">
<return-value transfer-ownership="full">
<type name="Object" c:type="FooObject"/>
</field>
</class>
- <record name="SubobjectClass" c:type="FooSubobjectClass">
+ <record name="SubobjectClass"
+ c:type="FooSubobjectClass"
+ glib:is-class-struct-for="Subobject">
<field name="parent_class">
<type name="ObjectClass" c:type="FooObjectClass"/>
</field>
c:type="FooBuffer"
parent="GObject.Object"
glib:type-name="FooBuffer"
- glib:get-type="foo_buffer_get_type">
+ glib:get-type="foo_buffer_get_type"
+ glib:class-struct="BufferClass">
<implements name="Interface"/>
<method name="some_method" c:identifier="foo_buffer_some_method">
<return-value transfer-ownership="none">
</return-value>
</method>
</class>
- <record name="BufferClass" c:type="FooBufferClass">
+ <record name="BufferClass"
+ c:type="FooBufferClass"
+ glib:is-class-struct-for="Buffer">
</record>
<function name="init" c:identifier="foo_init">
<return-value transfer-ownership="none">
<type name="GObject.TypeInterface"/>
</field>
</record>
- <class name="Object" parent="GObject.Object" glib:type-name="FooObject" glib:get-type="foo_object_get_type">
+ <class name="Object" parent="GObject.Object" glib:class-struct="ObjectClass" glib:type-name="FooObject" glib:get-type="foo_object_get_type">
<implements name="Interface"/>
<field name="parent_instance">
<type name="GObject.Object"/>
</parameters>
</glib:signal>
</class>
- <record name="ObjectClass">
+ <record name="ObjectClass" glib:is-class-struct="1">
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
</record>
- <class name="Subobject" parent="Object" abstract="1" glib:type-name="FooSubobject" glib:get-type="foo_subobject_get_type">
+ <class name="Subobject" parent="Object" glib:class-struct="SubobjectClass" abstract="1" glib:type-name="FooSubobject" glib:get-type="foo_subobject_get_type">
<implements name="Interface"/>
<field name="parent_instance">
<type name="Object"/>
</return-value>
</constructor>
</class>
- <record name="SubobjectClass">
+ <record name="SubobjectClass" glib:is-class-struct="1">
<field name="parent_class">
<type name="ObjectClass"/>
</field>
</record>
- <class name="Buffer" parent="GObject.Object" glib:type-name="FooBuffer" glib:get-type="foo_buffer_get_type">
+ <class name="Buffer" parent="GObject.Object" glib:class-struct="BufferClass" glib:type-name="FooBuffer" glib:get-type="foo_buffer_get_type">
<implements name="Interface"/>
<method name="some_method" c:identifier="foo_buffer_some_method">
<return-value transfer-ownership="none">
</return-value>
</method>
</class>
- <record name="BufferClass"/>
+ <record name="BufferClass" glib:is-class-struct="1"/>
<function name="init" c:identifier="foo_init">
<return-value transfer-ownership="none">
<type name="int"/>
c:type="UtilityObject"
parent="GObject.Object"
glib:type-name="UtilityObject"
- glib:get-type="utility_object_get_type">
+ glib:get-type="utility_object_get_type"
+ glib:class-struct="ObjectClass">
<method name="watch_dir" c:identifier="utility_object_watch_dir">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
<type name="GObject.Object" c:type="GObject"/>
</field>
</class>
- <record name="ObjectClass" c:type="UtilityObjectClass">
+ <record name="ObjectClass"
+ c:type="UtilityObjectClass"
+ glib:is-class-struct-for="Object">
<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
<include name="GObject" version="2.0"/>
<include name="GLib" version="2.0"/>
<namespace name="utility" version="1.0" shared-library="utility">
- <class name="Object" parent="GObject.Object" glib:type-name="UtilityObject" glib:get-type="utility_object_get_type">
+ <class name="Object" parent="GObject.Object" glib:class-struct="ObjectClass" glib:type-name="UtilityObject" glib:get-type="utility_object_get_type">
<field name="parent_instance">
<type name="GObject.Object"/>
</field>
</parameters>
</method>
</class>
- <record name="ObjectClass">
+ <record name="ObjectClass" glib:is-class-struct="1">
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
const gchar *type_name;
const gchar *type_init;
gboolean deprecated;
+ gboolean is_class_struct;
gint i;
int n_elts;
if (deprecated)
xml_printf (file, " deprecated=\"1\"");
+
+ is_class_struct = g_struct_info_is_class_struct (info);
+ if (is_class_struct)
+ xml_printf (file, " glib:is-class-struct=\"1\"");
n_elts = g_struct_info_get_n_fields (info) + g_struct_info_get_n_methods (info);
if (n_elts > 0)
gboolean deprecated;
gboolean is_abstract;
GIObjectInfo *pnode;
+ GIStructInfo *class_struct;
gint i;
name = g_base_info_get_name ((GIBaseInfo *)info);
write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
g_base_info_unref ((GIBaseInfo *)pnode);
}
+
+ class_struct = g_object_info_get_class_struct (info);
+ if (class_struct)
+ {
+ write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:class-struct", file);
+ g_base_info_unref ((GIBaseInfo*)class_struct);
+ }
if (is_abstract)
xml_printf (file, " abstract=\"1\"");