diff options
author | James Henstridge <james@daa.com.au> | 2000-10-26 12:48:17 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2000-10-26 12:48:17 +0000 |
commit | 03cf5b7534de8da2af941cf0a11b92ae078cf19d (patch) | |
tree | b3cd29440f7f6b9b6e291effde333406c7d23e5f | |
parent | e951bb46a26cee1abcf4540a9de79642158c0fda (diff) | |
download | pygtk-03cf5b7534de8da2af941cf0a11b92ae078cf19d.tar.gz |
new function for registering functions to marshal boxed GValues to/from
2000-10-26 James Henstridge <james@daa.com.au>
* gobjectmodule.c (pyg_boxed_register): new function for
registering functions to marshal boxed GValues to/from their
python wrappers.
(pyg_value_from_pyobject): add boxed support.
(pyg_value_as_pyobject): add boxed support.
(pyg_closure_new): new function to create a python GClosure.
(pyg_closure_destroy): cleanup function for a PyGClosure.
(pyg_closure_marshal): marshaler for PyGClosure.
(pyg_value_as_pyobject): add const to GValue argument.
* pygobject.h: export a pyg_boxed_register function to register
new boxed types for use with pyg_value_from_pyobject and
pyg_value_as_pyobject.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | gobject/gobjectmodule.c | 134 | ||||
-rw-r--r-- | gobject/pygobject.h | 22 | ||||
-rw-r--r-- | gobjectmodule.c | 134 | ||||
-rw-r--r-- | pygobject.h | 22 |
5 files changed, 308 insertions, 20 deletions
@@ -1,3 +1,19 @@ +2000-10-26 James Henstridge <james@daa.com.au> + + * gobjectmodule.c (pyg_boxed_register): new function for + registering functions to marshal boxed GValues to/from their + python wrappers. + (pyg_value_from_pyobject): add boxed support. + (pyg_value_as_pyobject): add boxed support. + (pyg_closure_new): new function to create a python GClosure. + (pyg_closure_destroy): cleanup function for a PyGClosure. + (pyg_closure_marshal): marshaler for PyGClosure. + (pyg_value_as_pyobject): add const to GValue argument. + + * pygobject.h: export a pyg_boxed_register function to register + new boxed types for use with pyg_value_from_pyobject and + pyg_value_as_pyobject. + 2000-10-25 James Henstridge <james@daa.com.au> * gtk/gtkmodule.c (init_gtk): set the default python character diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index d2a50ee3..a834fe10 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -203,6 +203,29 @@ pyg_flags_get_value(GType flag_type, PyObject *obj, gint *val) return res; } +typedef PyObject *(* fromvaluefunc)(const GValue *value); +typedef int (*tovaluefunc)(GValue *value, PyObject *obj); +typedef struct { + fromvaluefunc fromvalue; + tovaluefunc tovalue; +} PyGBoxedMarshal; +static GHashTable *boxed_marshalers; +#define pyg_boxed_lookup(boxed_type) \ + ((PyGBoxedMarshal *)g_hash_table_lookup(boxed_marshalers, \ + GUINT_TO_POINTER(boxed_type))) + +static void +pyg_boxed_register(GType boxed_type, + PyObject *(* from_func)(const GValue *value), + int (* to_func)(GValue *value, PyObject *obj)) +{ + PyGBoxedMarshal *bm = g_new(PyGBoxedMarshal, 1); + + bm->fromvalue = from_func; + bm->tovalue = to_func; + g_hash_table_insert(boxed_marshalers, GUINT_TO_POINTER(boxed_type), bm); +} + static int pyg_value_from_pyobject(GValue *value, PyObject *obj) { @@ -298,12 +321,17 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) return -1; g_value_set_flags(value, val); + } else if (G_IS_VALUE_BOXED(value)) { + PyGBoxedMarshal *bm = pyg_boxed_lookup(G_VALUE_TYPE(value)); + + if (!bm || bm->tovalue(value, obj) < 0) + return -1; } return 0; } static PyObject * -pyg_value_as_pyobject(GValue *value) +pyg_value_as_pyobject(const GValue *value) { if (G_IS_VALUE_CHAR(value)) { gint8 val = g_value_get_char(value); @@ -331,11 +359,112 @@ pyg_value_as_pyobject(GValue *value) return PyInt_FromLong(g_value_get_enum(value)); } else if (G_IS_VALUE_FLAGS(value)) { return PyInt_FromLong(g_value_get_flags(value)); + } else if (G_IS_VALUE_BOXED(value)) { + PyGBoxedMarshal *bm = pyg_boxed_lookup(G_VALUE_TYPE(value)); + + if (bm) + return bm->fromvalue(value); + /* fall through if unknown boxed type */ } PyErr_SetString(PyExc_TypeError, "unknown type"); return NULL; } +/* -------------- PyGClosure ----------------- */ + +typedef struct _PyGClosure PyGClosure; +struct _PyGClosure { + GClosure closure; + PyObject *callback; + PyObject *extra_args; /* tuple of extra args to pass to callback */ + PyObject *swap_data; /* other object for gtk_signal_connect_object */ +}; + +/* XXXX - must handle multithreadedness here */ +static void +pyg_closure_destroy(gpointer data, GClosure *closure) +{ + PyGClosure *pc = (PyGClosure *)closure; + + Py_DECREF(pc->callback); + Py_XDECREF(pc->extra_args); + Py_XDECREF(pc->swap_data); +} + +/* XXXX - need to handle python thread context stuff */ +static void +pyg_closure_marshal(GClosure *closure, + guint invocation_hint, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer marshal_data) +{ + PyGClosure *pc = (PyGClosure *)closure; + PyObject *params, *ret; + guint i; + + /* construct Python tuple for the parameter values */ + params = PyTuple_New(n_param_values); + for (i = 0; i < n_param_values; i++) { + /* swap in a different initial data for connect_object() */ + if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) { + g_return_if_fail(pc->swap_data != NULL); + Py_INCREF(pc->swap_data); + PyTuple_SetItem(params, 0, pc->swap_data); + } else { + 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); + } + } + /* params passed to function may have extra arguments */ + if (pc->extra_args) { + PyObject *tuple = params; + params = PySequence_Concat(tuple, pc->extra_args); + Py_DECREF(tuple); + } + ret = PyObject_CallObject(pc->callback, params); + if (ret == NULL) { + /* XXXX - do fatal exceptions thing here */ + PyErr_Print(); + PyErr_Clear(); + /* XXXX - clean up if threading was used */ + return; + } + pyg_value_from_pyobject(return_value, ret); + Py_DECREF(ret); + /* XXXX - clean up if threading was used */ +} + +static GClosure * +pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data) +{ + GClosure *closure; + + g_return_val_if_fail(callback != NULL, NULL); + closure = g_closure_new_simple(sizeof(PyGClosure), NULL); + g_closure_add_fnotify(closure, NULL, pyg_closure_destroy); + g_closure_set_marshal(closure, pyg_closure_marshal); + Py_INCREF(callback); + ((PyGClosure *)closure)->callback = callback; + if (extra_args) { + Py_INCREF(extra_args); + ((PyGClosure *)closure)->extra_args = extra_args; + } + if (swap_data) { + Py_INCREF(swap_data); + ((PyGClosure *)closure)->swap_data; + closure->derivative_flag = TRUE; + } +} + /* -------------- PyGObject behaviour ----------------- */ static void pygobject_dealloc(PyGObject *self) @@ -660,6 +789,7 @@ static struct _PyGObject_Functions functions = { pygobject_new, pyg_enum_get_value, pyg_flags_get_value, + pyg_boxed_register, pyg_value_from_pyobject, pyg_value_as_pyobject, }; @@ -675,6 +805,8 @@ initgobject(void) g_type_init(); pygobject_register_class(d, "GObject", &PyGObject_Type, NULL); + boxed_marshalers = g_hash_table_new(g_direct_hash, g_direct_equal); + pygobject_wrapper_key = g_quark_from_static_string("py-gobject-wrapper"); pygobject_ownedref_key = g_quark_from_static_string("py-gobject-ownedref"); diff --git a/gobject/pygobject.h b/gobject/pygobject.h index 62b1922b..88235144 100644 --- a/gobject/pygobject.h +++ b/gobject/pygobject.h @@ -19,15 +19,18 @@ typedef struct { #define pygobject_check(v,base) (ExtensionClassSubclassInstance_Check(v,base)) struct _PyGObject_Functions { - void (* register_class)(PyObject *dict, const gchar *class_name, - PyExtensionClass *ec, PyExtensionClass *parent); - void (* register_wrapper)(PyObject *self); - PyExtensionClass *(* lookup_class)(GType type); - PyObject *(* new)(GObject *obj); - gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val); - gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val); - int (* value_from_pyobject)(GValue *value, PyObject *obj); - PyObject *(* value_as_pyobject)(GValue *value); + void (* register_class)(PyObject *dict, const gchar *class_name, + PyExtensionClass *ec, PyExtensionClass *parent); + void (* register_wrapper)(PyObject *self); + PyExtensionClass *(* lookup_class)(GType type); + PyObject *(* new)(GObject *obj); + gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val); + gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val); + void (* boxed_register)(GType boxed_type, + PyObject *(* from_func)(const GValue *value), + int (* to_func)(GValue *value, PyObject *obj)); + int (* value_from_pyobject)(GValue *value, PyObject *obj); + PyObject *(* value_as_pyobject)(const GValue *value); }; #ifndef _INSIDE_PYGOBJECT_ @@ -44,6 +47,7 @@ struct _PyGObject_Functions *_PyGObject_API; #define pygobject_new (_PyGObject_API->new) #define pyg_enum_get_value (_PyGObject_API->enum_get_value) #define pyg_flags_get_value (_PyGObject_API->flags_get_value) +#define pyg_boxed_register (_PyGObject_API->boxed_register) #define pyg_value_from_pyobject (_PyGObject_API->value_from_pyobject) #define pyg_value_as_pyobject (_PyGObject_API->value_as_pyobject) diff --git a/gobjectmodule.c b/gobjectmodule.c index d2a50ee3..a834fe10 100644 --- a/gobjectmodule.c +++ b/gobjectmodule.c @@ -203,6 +203,29 @@ pyg_flags_get_value(GType flag_type, PyObject *obj, gint *val) return res; } +typedef PyObject *(* fromvaluefunc)(const GValue *value); +typedef int (*tovaluefunc)(GValue *value, PyObject *obj); +typedef struct { + fromvaluefunc fromvalue; + tovaluefunc tovalue; +} PyGBoxedMarshal; +static GHashTable *boxed_marshalers; +#define pyg_boxed_lookup(boxed_type) \ + ((PyGBoxedMarshal *)g_hash_table_lookup(boxed_marshalers, \ + GUINT_TO_POINTER(boxed_type))) + +static void +pyg_boxed_register(GType boxed_type, + PyObject *(* from_func)(const GValue *value), + int (* to_func)(GValue *value, PyObject *obj)) +{ + PyGBoxedMarshal *bm = g_new(PyGBoxedMarshal, 1); + + bm->fromvalue = from_func; + bm->tovalue = to_func; + g_hash_table_insert(boxed_marshalers, GUINT_TO_POINTER(boxed_type), bm); +} + static int pyg_value_from_pyobject(GValue *value, PyObject *obj) { @@ -298,12 +321,17 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) return -1; g_value_set_flags(value, val); + } else if (G_IS_VALUE_BOXED(value)) { + PyGBoxedMarshal *bm = pyg_boxed_lookup(G_VALUE_TYPE(value)); + + if (!bm || bm->tovalue(value, obj) < 0) + return -1; } return 0; } static PyObject * -pyg_value_as_pyobject(GValue *value) +pyg_value_as_pyobject(const GValue *value) { if (G_IS_VALUE_CHAR(value)) { gint8 val = g_value_get_char(value); @@ -331,11 +359,112 @@ pyg_value_as_pyobject(GValue *value) return PyInt_FromLong(g_value_get_enum(value)); } else if (G_IS_VALUE_FLAGS(value)) { return PyInt_FromLong(g_value_get_flags(value)); + } else if (G_IS_VALUE_BOXED(value)) { + PyGBoxedMarshal *bm = pyg_boxed_lookup(G_VALUE_TYPE(value)); + + if (bm) + return bm->fromvalue(value); + /* fall through if unknown boxed type */ } PyErr_SetString(PyExc_TypeError, "unknown type"); return NULL; } +/* -------------- PyGClosure ----------------- */ + +typedef struct _PyGClosure PyGClosure; +struct _PyGClosure { + GClosure closure; + PyObject *callback; + PyObject *extra_args; /* tuple of extra args to pass to callback */ + PyObject *swap_data; /* other object for gtk_signal_connect_object */ +}; + +/* XXXX - must handle multithreadedness here */ +static void +pyg_closure_destroy(gpointer data, GClosure *closure) +{ + PyGClosure *pc = (PyGClosure *)closure; + + Py_DECREF(pc->callback); + Py_XDECREF(pc->extra_args); + Py_XDECREF(pc->swap_data); +} + +/* XXXX - need to handle python thread context stuff */ +static void +pyg_closure_marshal(GClosure *closure, + guint invocation_hint, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer marshal_data) +{ + PyGClosure *pc = (PyGClosure *)closure; + PyObject *params, *ret; + guint i; + + /* construct Python tuple for the parameter values */ + params = PyTuple_New(n_param_values); + for (i = 0; i < n_param_values; i++) { + /* swap in a different initial data for connect_object() */ + if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) { + g_return_if_fail(pc->swap_data != NULL); + Py_INCREF(pc->swap_data); + PyTuple_SetItem(params, 0, pc->swap_data); + } else { + 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); + } + } + /* params passed to function may have extra arguments */ + if (pc->extra_args) { + PyObject *tuple = params; + params = PySequence_Concat(tuple, pc->extra_args); + Py_DECREF(tuple); + } + ret = PyObject_CallObject(pc->callback, params); + if (ret == NULL) { + /* XXXX - do fatal exceptions thing here */ + PyErr_Print(); + PyErr_Clear(); + /* XXXX - clean up if threading was used */ + return; + } + pyg_value_from_pyobject(return_value, ret); + Py_DECREF(ret); + /* XXXX - clean up if threading was used */ +} + +static GClosure * +pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data) +{ + GClosure *closure; + + g_return_val_if_fail(callback != NULL, NULL); + closure = g_closure_new_simple(sizeof(PyGClosure), NULL); + g_closure_add_fnotify(closure, NULL, pyg_closure_destroy); + g_closure_set_marshal(closure, pyg_closure_marshal); + Py_INCREF(callback); + ((PyGClosure *)closure)->callback = callback; + if (extra_args) { + Py_INCREF(extra_args); + ((PyGClosure *)closure)->extra_args = extra_args; + } + if (swap_data) { + Py_INCREF(swap_data); + ((PyGClosure *)closure)->swap_data; + closure->derivative_flag = TRUE; + } +} + /* -------------- PyGObject behaviour ----------------- */ static void pygobject_dealloc(PyGObject *self) @@ -660,6 +789,7 @@ static struct _PyGObject_Functions functions = { pygobject_new, pyg_enum_get_value, pyg_flags_get_value, + pyg_boxed_register, pyg_value_from_pyobject, pyg_value_as_pyobject, }; @@ -675,6 +805,8 @@ initgobject(void) g_type_init(); pygobject_register_class(d, "GObject", &PyGObject_Type, NULL); + boxed_marshalers = g_hash_table_new(g_direct_hash, g_direct_equal); + pygobject_wrapper_key = g_quark_from_static_string("py-gobject-wrapper"); pygobject_ownedref_key = g_quark_from_static_string("py-gobject-ownedref"); diff --git a/pygobject.h b/pygobject.h index 62b1922b..88235144 100644 --- a/pygobject.h +++ b/pygobject.h @@ -19,15 +19,18 @@ typedef struct { #define pygobject_check(v,base) (ExtensionClassSubclassInstance_Check(v,base)) struct _PyGObject_Functions { - void (* register_class)(PyObject *dict, const gchar *class_name, - PyExtensionClass *ec, PyExtensionClass *parent); - void (* register_wrapper)(PyObject *self); - PyExtensionClass *(* lookup_class)(GType type); - PyObject *(* new)(GObject *obj); - gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val); - gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val); - int (* value_from_pyobject)(GValue *value, PyObject *obj); - PyObject *(* value_as_pyobject)(GValue *value); + void (* register_class)(PyObject *dict, const gchar *class_name, + PyExtensionClass *ec, PyExtensionClass *parent); + void (* register_wrapper)(PyObject *self); + PyExtensionClass *(* lookup_class)(GType type); + PyObject *(* new)(GObject *obj); + gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val); + gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val); + void (* boxed_register)(GType boxed_type, + PyObject *(* from_func)(const GValue *value), + int (* to_func)(GValue *value, PyObject *obj)); + int (* value_from_pyobject)(GValue *value, PyObject *obj); + PyObject *(* value_as_pyobject)(const GValue *value); }; #ifndef _INSIDE_PYGOBJECT_ @@ -44,6 +47,7 @@ struct _PyGObject_Functions *_PyGObject_API; #define pygobject_new (_PyGObject_API->new) #define pyg_enum_get_value (_PyGObject_API->enum_get_value) #define pyg_flags_get_value (_PyGObject_API->flags_get_value) +#define pyg_boxed_register (_PyGObject_API->boxed_register) #define pyg_value_from_pyobject (_PyGObject_API->value_from_pyobject) #define pyg_value_as_pyobject (_PyGObject_API->value_as_pyobject) |