summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Henstridge <james@daa.com.au>2000-10-26 12:48:17 +0000
committerJames Henstridge <jamesh@src.gnome.org>2000-10-26 12:48:17 +0000
commit05fe6d04db97488157bf618fda5cdd3cc107abce (patch)
tree2ec27044806d250dd26b5f64ca1bf73c10ede404
parent4e562b13acd6918c1fb9909ae95067b1b91702b4 (diff)
downloadpygobject-05fe6d04db97488157bf618fda5cdd3cc107abce.tar.gz
pygobject-05fe6d04db97488157bf618fda5cdd3cc107abce.tar.xz
pygobject-05fe6d04db97488157bf618fda5cdd3cc107abce.zip
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--gobject/gobjectmodule.c134
-rw-r--r--gobject/pygobject.h22
2 files changed, 146 insertions, 10 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index d2a50ee..a834fe1 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(&param_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 62b1922..8823514 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)