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
This commit is contained in:
Johan Dahlin 2010-06-12 18:08:56 -03:00
parent 68b4fb43bb
commit b6d50e2951
10 changed files with 445 additions and 7 deletions

55
gdump.c
View File

@ -270,6 +270,56 @@ dump_enum_type (GType type, const char *symbol, GOutputStream *out)
goutput_write (out, " </enum>");
}
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)
{
@ -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;
}
}

View File

@ -96,6 +96,29 @@ g_object_info_get_abstract (GIObjectInfo *info)
return blob->abstract != 0;
}
/**
* 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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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\"");

View File

@ -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;

View File

@ -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);