diff options
author | Johan Dahlin <johan@src.gnome.org> | 2006-07-13 17:26:56 +0000 |
---|---|---|
committer | Johan Dahlin <johan@src.gnome.org> | 2006-07-13 17:26:56 +0000 |
commit | e26921db6615d6ab766ecb10049af254e43eeaa3 (patch) | |
tree | 65cf78bda92ddf9f68f243bea929853f24bf873f | |
parent | f80b6b9f96a027d926c9ee3d31f0ca8eb05272bf (diff) | |
download | pygobject-e26921db6615d6ab766ecb10049af254e43eeaa3.tar.gz pygobject-e26921db6615d6ab766ecb10049af254e43eeaa3.tar.xz pygobject-e26921db6615d6ab766ecb10049af254e43eeaa3.zip |
Add infrastructure for lazy type registration, fixes #
* gobject/gobjectmodule.c: (pyg_type_from_name),
(get_type_name_for_class):
* gobject/pygobject-private.h:
* gobject/pygobject.c: (pygobject_new_with_interfaces),
(pygobject_lookup_class), (pygobject_emit):
* gobject/pygobject.h:
* gobject/pygtype.c: (_wrap_g_type_from_name),
(pyg_type_from_object), (pyg_type_register_custom_callback),
(pyg_type_get_custom), (_pyg_type_from_name):
Add infrastructure for lazy type registration, fixes #
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | gobject/gobjectmodule.c | 8 | ||||
-rw-r--r-- | gobject/pygobject-private.h | 7 | ||||
-rw-r--r-- | gobject/pygobject.c | 11 | ||||
-rw-r--r-- | gobject/pygobject.h | 8 | ||||
-rw-r--r-- | gobject/pygtype.c | 79 |
6 files changed, 116 insertions, 11 deletions
@@ -1,3 +1,17 @@ +2006-07-13 Johan Dahlin <jdahlin@async.com.br> + + reviewed by: <delete if not using a buddy> + + * gobject/gobjectmodule.c: (pyg_type_from_name), + (get_type_name_for_class): + * gobject/pygobject-private.h: + * gobject/pygobject.c: (pygobject_new_with_interfaces), + (pygobject_lookup_class), (pygobject_emit): + * gobject/pygobject.h: + * gobject/pygtype.c: (_wrap_g_type_from_name), + (pyg_type_from_object), (pyg_type_register_custom_callback), + (pyg_type_get_custom), (_pyg_type_from_name): + 2006-07-13 Gustavo J. A. M. Carneiro <gjc@inescporto.pt> * m4/python.m4: Properly quote AM_CHECK_PYMOD definition. diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index d4909a9..0004f43 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -277,7 +277,7 @@ pyg_type_from_name (PyObject *self, PyObject *args) #endif if (!PyArg_ParseTuple(args, "s:gobject.type_from_name", &name)) return NULL; - type = g_type_from_name(name); + type = _pyg_type_from_name(name); if (type != 0) return pyg_type_wrapper_new(type); PyErr_Format(PyExc_RuntimeError, "%s: unknown type name: %s", @@ -1136,7 +1136,7 @@ get_type_name_for_class(PyTypeObject *class) for (i = 0; type_name[i] != '\0'; i++) if (type_name[i] == '.') type_name[i] = '+'; - if (g_type_from_name(type_name) == 0) + if (_pyg_type_from_name(type_name) == 0) break; /* we now have a unique name */ ++name_serial; } @@ -3241,7 +3241,9 @@ struct _PyGObject_Functions pygobject_api_functions = { pyg_set_object_has_new_constructor, add_warning_redirection, - disable_warning_redirections + disable_warning_redirections, + + pyg_type_register_custom_callback }; #define REGISTER_TYPE(d, type, name) \ diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h index 2b6ac73..9553600 100644 --- a/gobject/pygobject-private.h +++ b/gobject/pygobject-private.h @@ -253,4 +253,11 @@ PyObject * pyg_option_context_new (GOptionContext * context); PyObject * pyg_option_group_new (GOptionGroup * group); GOptionGroup *pyg_option_group_transfer_group(PyGOptionGroup *self); +extern GHashTable *custom_type_registration; +void pyg_type_register_custom_callback(const gchar *typename, + PyGTypeRegistrationFunction callback, + gpointer data); +PyTypeObject * pyg_type_get_custom(const gchar *name); +GType _pyg_type_from_name(const gchar *name); + #endif diff --git a/gobject/pygobject.c b/gobject/pygobject.c index 1451148..5660296 100644 --- a/gobject/pygobject.c +++ b/gobject/pygobject.c @@ -34,6 +34,8 @@ typedef struct { } SinkFunc; static GArray *sink_funcs = NULL; +GHashTable *custom_type_registration = NULL; + PyTypeObject *PyGObject_MetaType = NULL; /** @@ -636,7 +638,7 @@ pygobject_new_with_interfaces(GType gtype) PyDict_SetItemString(dict, "__doc__", pyg_object_descr_doc_get()); /* generate the pygtk module name and extract the base type name */ - gtype_name = (gchar *)g_type_name(gtype); + gtype_name = (gchar*)g_type_name(gtype); if (g_str_has_prefix(gtype_name, "Gtk")) { mod_name = "gtk"; gtype_name += 3; @@ -725,6 +727,10 @@ pygobject_lookup_class(GType gtype) if (gtype == G_TYPE_INTERFACE) return &PyGInterface_Type; + + py_type = pyg_type_get_custom(g_type_name(gtype)); + if (py_type) + return py_type; py_type = g_type_get_qdata(gtype, pygobject_class_key); if (py_type == NULL) { @@ -1513,7 +1519,8 @@ pygobject_emit(PyGObject *self, PyObject *args) g_free(params); return NULL; } - } + } + if (query.return_type != G_TYPE_NONE) g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); diff --git a/gobject/pygobject.h b/gobject/pygobject.h index 8eeb818..3e928c7 100644 --- a/gobject/pygobject.h +++ b/gobject/pygobject.h @@ -65,6 +65,8 @@ typedef struct { #define PyGParamSpec_Check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type)) typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass); +typedef PyTypeObject * (*PyGTypeRegistrationFunction) (const gchar *name, + gpointer data); struct _PyGObject_Functions { /* @@ -176,6 +178,10 @@ struct _PyGObject_Functions { void (*add_warning_redirection) (const char *domain, PyObject *warning); void (*disable_warning_redirections) (void); + void (*type_register_custom)(const gchar *typename, + PyGTypeRegistrationFunction callback, + gpointer data); + }; #ifndef _INSIDE_PYGOBJECT_ @@ -237,7 +243,7 @@ struct _PyGObject_Functions *_PyGObject_API; #define pyg_set_object_has_new_constructor (_PyGObject_API->set_object_has_new_constructor) #define pyg_add_warning_redirection (_PyGObject_API->add_warning_redirection) #define pyg_disable_warning_redirections (_PyGObject_API->disable_warning_redirections) - +#define pyg_type_register_custom_callback (_PyGObject_API->type_register_custom) #define pyg_block_threads() G_STMT_START { \ if (_PyGObject_API->block_threads != NULL) \ diff --git a/gobject/pygtype.c b/gobject/pygtype.c index 3315b29..efbabb7 100644 --- a/gobject/pygtype.c +++ b/gobject/pygtype.c @@ -206,7 +206,7 @@ _wrap_g_type_from_name(PyGTypeWrapper *_, PyObject *args) if (!PyArg_ParseTuple(args, "s:GType.from_name", &type_name)) return NULL; - type = g_type_from_name(type_name); + type = _pyg_type_from_name(type_name); if (type == 0) { PyErr_SetString(PyExc_RuntimeError, "unknown type name"); return NULL; @@ -373,14 +373,17 @@ pyg_type_from_object(PyObject *obj) /* handle strings */ if (PyString_Check(obj)) { - type = g_type_from_name(PyString_AsString(obj)); - if (type == 0) - PyErr_SetString(PyExc_TypeError, "could not find named typecode"); - return type; + gchar *name = PyString_AsString(obj); + + type = _pyg_type_from_name(name); + if (type != 0) { + return type; + } } /* finally, look for a __gtype__ attribute on the object */ gtype = PyObject_GetAttrString(obj, "__gtype__"); + if (gtype) { if (gtype->ob_type == &PyGTypeWrapper_Type) { type = ((PyGTypeWrapper *)gtype)->type; @@ -1637,3 +1640,69 @@ pyg_param_gvalue_as_pyobject(const GValue* gvalue, return pyg_value_as_pyobject(gvalue, copy_boxed); } } + +/** + * pyg_type_registration_callback + * @gtypename: type name + * @callback: function to run + * + */ +typedef struct { + PyGTypeRegistrationFunction callback; + gpointer data; +} CustomTypeData; + +void +pyg_type_register_custom_callback(const gchar *typename, + PyGTypeRegistrationFunction callback, + gpointer user_data) +{ + CustomTypeData *data; + + if (!custom_type_registration) + custom_type_registration = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); + + data = g_new (CustomTypeData, 1); + data->callback = callback; + data->data = user_data; + + g_hash_table_insert(custom_type_registration, + g_strdup(typename), + data); +} + +PyTypeObject * +pyg_type_get_custom(const gchar *name) +{ + CustomTypeData *data; + PyTypeObject *retval; + + if (!custom_type_registration) + return NULL; + + data = g_hash_table_lookup(custom_type_registration, name); + if (!data) + return NULL; + + retval = data->callback(name, data->data); + + g_hash_table_remove(custom_type_registration, name); + + return retval; +} + +GType +_pyg_type_from_name(const gchar *name) +{ + GType type; + + type = g_type_from_name(name); + if (type == G_TYPE_INVALID) { + pyg_type_get_custom(name); + type = g_type_from_name(name); + } + + return type; +} + |