diff options
author | James Henstridge <james@daa.com.au> | 2001-03-27 03:26:45 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2001-03-27 03:26:45 +0000 |
commit | d0aaf23e9ae87dc78a5403e916756b7b67f45541 (patch) | |
tree | c6f1dad3280f5589c44b1b4cebc22b21a94d435c | |
parent | 93b48a65ae29ff90551f44d417cd6763603d41d9 (diff) | |
download | pygobject-d0aaf23e9ae87dc78a5403e916756b7b67f45541.tar.gz pygobject-d0aaf23e9ae87dc78a5403e916756b7b67f45541.tar.xz pygobject-d0aaf23e9ae87dc78a5403e916756b7b67f45541.zip |
new function to get the closure used as the `class closure' for signals.
2001-03-27 James Henstridge <james@daa.com.au>
* gobjectmodule.c (pyg_signal_class_closure_get): new function to
get the closure used as the `class closure' for signals. We only
need one, as we can get all the information we need from the
invocation hint.
-rw-r--r-- | gobject/gobjectmodule.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 786d77d..f65c0e8 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -643,6 +643,99 @@ pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data) return closure; } +/* -------------- PySignalClassClosure ----------------- */ +/* a closure used for the `class closure' of a signal. As this gets + * all the info from the first argument to the closure and the + * invocation hint, we can have a single closure that handles all + * class closure cases. We call a method by the name of the signal + * with "do_" prepended. + * + * We also remove the first argument from the * param list, as it is + * the instance object, which is passed * implicitly to the method + * object. */ + +static void +pyg_signal_class_closure_marshal(GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + GObject *object; + PyObject *object_wrapper; + GSignalInvocationHint *hint = (GSignalInvocationHint *)invocation_hint; + gchar *method_name; + PyObject *method; + PyObject *params, *ret; + guint i; + + g_return_if_fail(invocation_hint != NULL); + + /* get the object passed as the first argument to the closure */ + object = g_value_get_object(¶m_values[0]); + g_return_if_fail(object != NULL && G_IS_OBJECT(object)); + + /* get the wrapper for this object */ + object_wrapper = pygobject_new(object); + g_return_if_fail(object_wrapper != NULL); + + /* construct method name for this class closure */ + method_name = g_strconcat("do_", g_signal_name(hint->signal_id), NULL); + method = PyObject_GetAttrString(object_wrapper, method_name); + g_free(method_name); + if (!method) { + PyErr_Clear(); + Py_DECREF(object_wrapper); + g_message("no class closure to call"); + return; + } + Py_DECREF(object_wrapper); + + /* construct Python tuple for the parameter values */ + params = PyTuple_New(n_param_values - 1); + for (i = 1; i < n_param_values; i++) { + PyObject *item = pyg_value_as_pyobject(¶m_values[i]); + + /* error condition */ + if (!item) { + Py_DECREF(params); + /* XXXX - clean up if threading was used */ + return; + } + PyTuple_SetItem(params, i, item); + } + + ret = PyObject_CallObject(method, params); + if (ret == NULL) { + /* XXXX - do fatal exceptions thing here */ + PyErr_Print(); + PyErr_Clear(); + /* XXXX - clean up if threading was used */ + Py_DECREF(method); + return; + } + Py_DECREF(method); + pyg_value_from_pyobject(return_value, ret); + Py_DECREF(ret); + /* XXXX - clean up if threading was used */ +} + +static GClosure * +pyg_signal_class_closure_get(void) +{ + static GClosure *closure; + + if (closure == NULL) { + closure = g_closure_new_simple(sizeof(GClosure), NULL); + g_closure_set_marshal(closure, pyg_signal_class_closure_marshal); + + g_closure_ref(closure); + g_closure_sink(closure); + } + return closure; +} + /* -------------- PyGObject behaviour ----------------- */ static void pygobject_dealloc(PyGObject *self) |